1
1
<!-- - INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
2
2
/*
3
+
3
4
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
4
5
*/
5
6
@@ -16,34 +17,28 @@ import org.junit.Test
16
17
class SelectGuideTest {
17
18
-->
18
19
19
-
20
- ## Table of contents
21
-
22
20
<!-- - TOC -->
23
21
24
- * [ Select expression (experimental) ] ( #select-expression-experimental )
25
- * [ Selecting from channels ] ( #selecting-from-channels )
26
- * [ Selecting on close ] ( #selecting-on-close )
27
- * [ Selecting to send ] ( #selecting-to-send )
28
- * [ Selecting deferred values ] ( #selecting-deferred-values )
29
- * [ Switch over a channel of deferred values ] ( #switch-over-a-channel-of-deferred-values )
22
+ * [ select 表达式(试验性) ] ( #select-expression-experimental )
23
+ * [ 从通道查询 ] ( #selecting-from-channels )
24
+ * [ 从关闭的通道查询 ] ( #selecting-on-close )
25
+ * [ 查询并发送 ] ( #selecting-to-send )
26
+ * [ 查询延迟值 ] ( #selecting-deferred-values )
27
+ * [ 在延迟值通道上切换 ] ( #switch-over-a-channel-of-deferred-values )
30
28
31
29
<!-- - END_TOC -->
32
30
33
31
34
32
35
- ## Select expression (experimental)
33
+ ## select 表达式(试验性)
36
34
37
- Select expression makes it possible to await multiple suspending functions simultaneously and _ select_
38
- the first one that becomes available.
35
+ select 表达式可以同时等待多个挂起函数,并 _ 选择_ 第一个可用的。
39
36
40
- > Select expressions are an experimental feature of ` kotlinx.coroutines ` . Their API is expected to
41
- evolve in the upcoming updates of the ` kotlinx.coroutines ` library with potentially
42
- breaking changes.
37
+ > Select 表达式是 ` kotlinx.coroutines ` 的试验性功能。它们的 API 在 ` kotlinx.coroutines ` 库即将到来的更新中可能会有很大的变化。
43
38
44
- ### Selecting from channels
39
+ ### 从通道中查询
45
40
46
- Let us have two producers of strings: ` fizz ` and ` buzz ` . The ` fizz ` produces " Fizz" string every 300 ms:
41
+ 我们现在有两个字符串生产者: ` fizz ` 和 ` buzz ` 。其中 ` fizz ` 生产者每300毫秒产出 “ Fizz” 字符串:
47
42
48
43
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
49
44
@@ -56,9 +51,9 @@ fun CoroutineScope.fizz() = produce<String> {
56
51
}
57
52
```
58
53
59
- </div >
60
54
61
- And the ` buzz ` produces "Buzz!" string every 500 ms:
55
+
56
+ 接着 ` buzz ` 每500毫秒产出 “Buzz!” 字符串:
62
57
63
58
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
64
59
@@ -71,11 +66,9 @@ fun CoroutineScope.buzz() = produce<String> {
71
66
}
72
67
```
73
68
74
- </div >
75
69
76
- Using [ receive] [ ReceiveChannel.receive ] suspending function we can receive _ either_ from one channel or the
77
- other. But [ select] expression allows us to receive from _ both_ simultaneously using its
78
- [ onReceive] [ ReceiveChannel.onReceive ] clauses:
70
+
71
+ 使用 [ receive] [ ReceiveChannel.receive ] 挂起函数,我们可以从一个或另一个通道接收数据。但是 [ select] 表达式允许我们使用其 [ onReceive] [ ReceiveChannel.onReceive ] 子句同时从两者接收:
79
72
80
73
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
81
74
@@ -92,9 +85,9 @@ suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<St
92
85
}
93
86
```
94
87
95
- </div >
96
88
97
- Let us run it all seven times:
89
+
90
+ 让我们运行7次:
98
91
99
92
<!-- - CLEAR -->
100
93
@@ -144,9 +137,9 @@ fun main() = runBlocking<Unit> {
144
137
145
138
</div >
146
139
147
- > You can get full code [ here ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-01.kt )
140
+ > 你可以点击 [ 这里 ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-01.kt ) 获得完整代码
148
141
149
- The result of this code is:
142
+ 这段代码的结果如下:
150
143
151
144
``` text
152
145
fizz -> 'Fizz'
@@ -160,12 +153,9 @@ buzz -> 'Buzz!'
160
153
161
154
<!-- - TEST -->
162
155
163
- ### Selecting on close
156
+ ### 从关闭的通道查询
164
157
165
- The [ onReceive] [ ReceiveChannel.onReceive ] clause in ` select ` fails when the channel is closed causing the corresponding
166
- ` select ` to throw an exception. We can use [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] clause to perform a
167
- specific action when the channel is closed. The following example also shows that ` select ` is an expression that returns
168
- the result of its selected clause:
158
+ select 中的 [ onReceive] [ ReceiveChannel.onReceive ] 子句在已经关闭的通道会失败,并导致相应的 ` select ` 抛出异常。我们可以使用 [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] 子句在关闭通道时执行特定操作。以下示例还显示了 ` select ` 是一个返回其查询方法结果的表达式:
169
159
170
160
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
171
161
@@ -189,8 +179,7 @@ suspend fun selectAorB(a: ReceiveChannel<String>, b: ReceiveChannel<String>): St
189
179
190
180
</div >
191
181
192
- Let's use it with channel ` a ` that produces "Hello" string four times and
193
- channel ` b ` that produces "World" four times:
182
+ 现在有一个产出四次 “Hello” 字符串的 ` a ` 通道、一个产出四次 “World” 字符串的 ` b ` 通道,我们在这两个通道上使用它:
194
183
195
184
<!-- - CLEAR -->
196
185
@@ -235,9 +224,9 @@ fun main() = runBlocking<Unit> {
235
224
236
225
</div >
237
226
238
- > You can get full code [ here ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-02.kt )
227
+ > 你可以点击 [ 这里 ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-02.kt ) 获得完整代码
239
228
240
- The result of this code is quite interesting, so we'll analyze it in mode detail:
229
+ 这段代码的结果非常有趣,所以我们将在模式细节中分析它:
241
230
242
231
``` text
243
232
a -> 'Hello 0'
@@ -252,23 +241,19 @@ Channel 'a' is closed
252
241
253
242
<!-- - TEST -->
254
243
255
- There are couple of observations to make out of it.
244
+ 有几个结果可以通过观察得出。
245
+
246
+ 首先,` select ` 偏向于第一个子句,当可以同时选到多个子句时,第一个子句将被选中。在这里,两个通道都在不断地生成字符串,因此作为 select 中的第一个子句的通道获胜。然而因为我们使用的是无缓冲通道,所以 ` a ` 在其发送调用时会不时被挂起,进而 ` b ` 也有机会发送。
256
247
257
- First of all, ` select ` is _ biased_ to the first clause. When several clauses are selectable at the same time,
258
- the first one among them gets selected. Here, both channels are constantly producing strings, so ` a ` channel,
259
- being the first clause in select, wins. However, because we are using unbuffered channel, the ` a ` gets suspended from
260
- time to time on its [ send] [ SendChannel.send ] invocation and gives a chance for ` b ` to send, too.
248
+ 第二个观察结果是,当通道已经关闭时,会立即选择 [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] 。
261
249
262
- The second observation, is that [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] gets immediately selected when the
263
- channel is already closed.
264
250
265
- ### Selecting to send
266
251
267
- Select expression has [ onSend] [ SendChannel.onSend ] clause that can be used for a great good in combination
268
- with a biased nature of selection.
252
+ ### 查询并发送
269
253
270
- Let us write an example of producer of integers that sends its values to a ` side ` channel when
271
- the consumers on its primary channel cannot keep up with it:
254
+ Select 表达式具有 [ onSend] [ SendChannel.onSend ] 子句,可以很好的与选择的偏向特性结合使用。
255
+
256
+ 我们来编写一个整数生成器的示例,当主通道上的消费者无法跟上它时,它会将值发送到 ` side ` 通道上:
272
257
273
258
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
274
259
@@ -286,7 +271,7 @@ fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
286
271
287
272
</div >
288
273
289
- Consumer is going to be quite slow, taking 250 ms to process each number:
274
+ 消费者将会非常缓慢,每个数值处理需要250毫秒:
290
275
291
276
<!-- - CLEAR -->
292
277
@@ -324,11 +309,11 @@ fun main() = runBlocking<Unit> {
324
309
```
325
310
326
311
</div >
327
-
328
- > You can get full code [ here ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-03.kt )
329
-
330
- So let us see what happens:
331
-
312
+
313
+ > 你可以点击 [ 这里 ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-03.kt ) 获得完整代码
314
+
315
+ 让我们看看会发生什么:
316
+
332
317
``` text
333
318
Consuming 1
334
319
Side channel has 2
@@ -345,11 +330,9 @@ Done consuming
345
330
346
331
<!-- - TEST -->
347
332
348
- ### Selecting deferred values
333
+ ### 查询延迟值
349
334
350
- Deferred values can be selected using [ onAwait] [ Deferred.onAwait ] clause.
351
- Let us start with an async function that returns a deferred string value after
352
- a random delay:
335
+ 延迟值可以使用 [ onAwait] [ Deferred.onAwait ] 子句查询。让我们启动一个延迟随机时间后返回延迟字符串的异步方法:
353
336
354
337
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
355
338
@@ -362,7 +345,7 @@ fun CoroutineScope.asyncString(time: Int) = async {
362
345
363
346
</div >
364
347
365
- Let us start a dozen of them with a random delay.
348
+ 让我们启动十几个,每个都延迟随机的时间。
366
349
367
350
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
368
351
@@ -375,10 +358,7 @@ fun CoroutineScope.asyncStringsList(): List<Deferred<String>> {
375
358
376
359
</div >
377
360
378
- Now the main function awaits for the first of them to complete and counts the number of deferred values
379
- that are still active. Note, that we've used here the fact that ` select ` expression is a Kotlin DSL,
380
- so we can provide clauses for it using an arbitrary code. In this case we iterate over a list
381
- of deferred values to provide ` onAwait ` clause for each deferred value.
361
+ 现在主函数等待第一个函数完成,并统计仍处于激活状态的延迟值的数量。注意,我们在这里的使用,事实上是把 ` select ` 表达式作为一种Kotlin DSL,所以我们可以用任意代码为它提供子句。在这种情况下,我们遍历一个延迟值的队列,为每个延迟值提供 ` onAwait ` 子句。
382
362
383
363
<!-- - CLEAR -->
384
364
@@ -418,9 +398,9 @@ fun main() = runBlocking<Unit> {
418
398
419
399
</div >
420
400
421
- > You can get full code [ here ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-04.kt )
401
+ > 你可以点击 [ 这里 ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-04.kt ) 获得完整代码
422
402
423
- The output is:
403
+ 输出如下:
424
404
425
405
``` text
426
406
Deferred 4 produced answer 'Waited for 128 ms'
@@ -429,11 +409,9 @@ Deferred 4 produced answer 'Waited for 128 ms'
429
409
430
410
<!-- - TEST -->
431
411
432
- ### Switch over a channel of deferred values
412
+ ### 在延迟值通道上切换
433
413
434
- Let us write a channel producer function that consumes a channel of deferred string values, waits for each received
435
- deferred value, but only until the next deferred value comes over or the channel is closed. This example puts together
436
- [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] and [ onAwait] [ Deferred.onAwait ] clauses in the same ` select ` :
414
+ 我们现在来编写一个通道生产者函数,它消费一个产生延迟字符串的通道,并等待每个接收的延迟值,但只在下一个延迟值到达或者通道关闭之前。此示例将 [ onReceiveOrNull] [ ReceiveChannel.onReceiveOrNull ] 和 [ onAwait] [ Deferred.onAwait ] 子句放在同一个 ` select ` 中:
437
415
438
416
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
439
417
@@ -462,7 +440,7 @@ fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel<Deferred<String>>) =
462
440
463
441
</div >
464
442
465
- To test it, we'll use a simple async function that resolves to a specified string after a specified time:
443
+ 为了测试它,我们将用一个简单的异步函数,它在特定的延迟后返回特定的字符串:
466
444
467
445
468
446
<div class =" sample " markdown =" 1 " theme =" idea " data-highlight-only >
@@ -476,8 +454,7 @@ fun CoroutineScope.asyncString(str: String, time: Long) = async {
476
454
477
455
</div >
478
456
479
- The main function just launches a coroutine to print results of ` switchMapDeferreds ` and sends some test
480
- data to it:
457
+ 主函数只是启动一个协程来打印 ` switchMapDeferreds ` 的结果并向它发送一些测试数据:
481
458
482
459
<!-- - CLEAR -->
483
460
@@ -537,9 +514,9 @@ fun main() = runBlocking<Unit> {
537
514
538
515
</div >
539
516
540
- > You can get full code [ here ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-05.kt )
517
+ > 你可以点击 [ 这里 ] ( ../core/kotlinx-coroutines-core/test/guide/example-select-05.kt ) 获得完整代码
541
518
542
- The result of this code:
519
+ 这段代码的结果:
543
520
544
521
``` text
545
522
BEGIN
@@ -552,6 +529,7 @@ Channel was closed
552
529
553
530
<!-- - MODULE kotlinx-coroutines-core -->
554
531
<!-- - INDEX kotlinx.coroutines -->
532
+
555
533
[ Deferred.onAwait ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/on-await.html
556
534
<!-- - INDEX kotlinx.coroutines.channels -->
557
535
[ ReceiveChannel.receive ] : https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.channels/-receive-channel/receive.html
0 commit comments