新聞中心

select 表達(dá)式可以同時等待多個掛起函數(shù),并 選擇 第?個可?的。
在通道中 select
我們現(xiàn)在有兩個字符串?產(chǎn)者:fizz 和 buzz 。其中 fizz 每 300 毫秒?成?個“Fizz”字符串:
fun CoroutineScope.fizz() = produce接著 buzz 每 500 毫秒?成?個“Buzz!”字符串:
fun CoroutineScope.buzz() = produce使? receive 掛起函數(shù),我們可以從兩個通道接收 其中?個 的數(shù)據(jù)。但是 select 表達(dá)式允許我們使? 其 onReceive ?句 同時 從兩者接收:
suspend fun selectFizzBuzz(fizz: ReceiveChannel讓我們運?代碼 7 次:
val fizz = fizz() val buzz = buzz() repeat(7) { selectFizzBuzz(fizz, buzz) } coroutineContext.cancelChildren() // 取消 fizz 和 buzz 協(xié)程這段代碼的執(zhí)?結(jié)果如下:
fizz -> 'Fizz' buzz -> 'Buzz!' fizz -> 'Fizz' fizz -> 'Fizz' buzz -> 'Buzz!' fizz -> 'Fizz' buzz -> 'Buzz!'通道關(guān)閉時 select
select 中的 onReceive ?句在已經(jīng)關(guān)閉的通道執(zhí)?會發(fā)?失敗,并導(dǎo)致相應(yīng)的 select 拋出異常。我 們可以使? onReceiveOrNull ?句在關(guān)閉通道時執(zhí)?特定操作。以下?例還顯?了 select 是?個返 回其查詢?法結(jié)果的表達(dá)式:
suspend fun selectAorB(a: ReceiveChannel注意,onReceiveOrNull 是?個僅在?于不可空元素的通道上定義的擴展函數(shù),以使關(guān)閉的通道與空值 之間不會出現(xiàn)意外的混亂。 現(xiàn)在有?個?成四次“Hello”字符串的 a 通道,和?個?成四次“World”字符串的 b 通道,我們在這 兩個通道上使?它:
val a = produce這段代碼的結(jié)果?常有趣,所以我們將在細(xì)節(jié)中分析它:
a -> 'Hello 0' a -> 'Hello 1' b -> 'World 0' a -> 'Hello 2' a -> 'Hello 3' b -> 'World 1' Channel 'a' is closed Channel 'a' is closed有?個結(jié)果可以通過觀察得出。
?先,select 偏向于 第?個?句,當(dāng)可以同時選到多個?句時,第?個?句將被選中。在這?,兩個通 道都在不斷地?成字符串,因此 a 通道作為 select 中的第?個?句獲勝。然?因為我們使?的是?緩 沖通道,所以 a 在其調(diào)? send 時會不時地被掛起,進(jìn)? b 也有機會發(fā)送。
第?個觀察結(jié)果是,當(dāng)通道已經(jīng)關(guān)閉時,會?即選擇 onReceiveOrNull。
Select 以發(fā)送
Select 表達(dá)式具有 onSend ?句,可以很好的與選擇的偏向特性結(jié)合使?。
我們來編寫?個整數(shù)?成器的?例,當(dāng)主通道上的消費者?法跟上它時,它會將值發(fā)送到 side 通道 上:
fun CoroutineScope.produceNumbers(side: SendChannel消費者將會?常緩慢,每個數(shù)值處理需要 250 毫秒:
val side = Channel讓我們看看會發(fā)?什么:
Consuming 1 Side channel has 2 Side channel has 3 Consuming 4 Side channel has 5 Side channel has 6 Consuming 7 Side channel has 8 Side channel has 9 Consuming 10 Done consumingSelect 延遲值
延遲值可以使? onAwait ?句查詢。讓我們啟動?個異步函數(shù),它在隨機的延遲后會延遲返回字符串:
fun CoroutineScope.asyncString(time: Int) = async { delay(time.toLong()) "Waited for $time ms" }讓我們隨機啟動?余個異步函數(shù),每個都延遲隨機的時間。
fun CoroutineScope.asyncStringsList(): List現(xiàn)在 main 函數(shù)在等待第?個函數(shù)完成,并統(tǒng)計仍處于激活狀態(tài)的延遲值的數(shù)量。注意,我們在這?使? select 表達(dá)式事實上是作為?種 Kotlin DSL,所以我們可以?任意代碼為它提供?句。在這種情況 下,我們遍歷?個延遲值的隊列,并為每個延遲值提供 onAwait ?句的調(diào)?。
val list = asyncStringsList() val result = select該輸出如下:
Deferred 4 produced answer 'Waited for 128 ms' 11 coroutines are still active在延遲值通道上切換
我們現(xiàn)在來編寫?個通道?產(chǎn)者函數(shù),它消費?個產(chǎn)?延遲字符串的通道,并等待每個接收的延遲值, 但它只在下?個延遲值到達(dá)或者通道關(guān)閉之前處于運?狀態(tài)。此?例將 onReceiveOrNull 和 onAwait ?句放在同?個 select 中:
fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel為了測試它,我們將??個簡單的異步函數(shù),它在特定的延遲后返回特定的字符串:
fun CoroutineScope.asyncString(str: String, time: Long) = async { delay(time) str }main 函數(shù)只是啟動?個協(xié)程來打印 switchMapDeferreds 的結(jié)果并向它發(fā)送?些測試數(shù)據(jù):
val chan = Channel這段代碼的執(zhí)?結(jié)果:
BEGIN Replace END Channel was closed本文名稱:kotlin協(xié)程——>select表達(dá)式(實驗性的)-創(chuàng)新互聯(lián)
轉(zhuǎn)載來于:http://ef60e0e.cn/article/jhhdd.html