真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

kotlin協(xié)程——>select表達(dá)式(實(shí)驗(yàn)性的)-創(chuàng)新互聯(lián)

select 表達(dá)式(實(shí)驗(yàn)性的)kotlin協(xié)程——>se
lect表達(dá)式(實(shí)驗(yàn)性的)

select 表達(dá)式可以同時(shí)等待多個(gè)掛起函數(shù),并 選擇 第?個(gè)可?的。

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站制作、成都網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)梓潼,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220

在通道中 select

我們現(xiàn)在有兩個(gè)字符串?產(chǎn)者:fizz 和 buzz 。其中 fizz 每 300 毫秒?成?個(gè)“Fizz”字符串:

fun CoroutineScope.fizz() = produce { while (true) { // 每 300 毫秒發(fā)送?個(gè) "Fizz" delay(300) send("Fizz") } }

接著 buzz 每 500 毫秒?成?個(gè)“Buzz!”字符串:

fun CoroutineScope.buzz() = produce { while (true) { // 每 500 毫秒發(fā)送?個(gè)"Buzz!" delay(500) send("Buzz!") } }

使? receive 掛起函數(shù),我們可以從兩個(gè)通道接收 其中?個(gè) 的數(shù)據(jù)。但是 select 表達(dá)式允許我們使? 其 onReceive ?句 同時(shí) 從兩者接收:

suspend fun selectFizzBuzz(fizz: ReceiveChannel, buzz: ReceiveChannel) { select { // 意味著該 select 表達(dá)式不返回任何結(jié)果 fizz.onReceive { value -> // 這是第?個(gè) select ?句 println("fizz -> '$value'") } buzz.onReceive { value -> // 這是第?個(gè) select ?句 println("buzz -> '$value'") } } }

讓我們運(yùn)?代碼 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)閉時(shí) select

select 中的 onReceive ?句在已經(jīng)關(guān)閉的通道執(zhí)?會(huì)發(fā)?失敗,并導(dǎo)致相應(yīng)的 select 拋出異常。我 們可以使? onReceiveOrNull ?句在關(guān)閉通道時(shí)執(zhí)?特定操作。以下?例還顯?了 select 是?個(gè)返 回其查詢?法結(jié)果的表達(dá)式:

suspend fun selectAorB(a: ReceiveChannel, b: ReceiveChannel): String = select { a.onReceiveOrNull { value -> if (value == null) "Channel 'a' is closed" else "a -> '$value'" } b.onReceiveOrNull { value -> if (value == null) "Channel 'b' is closed" else "b -> '$value'" } }

注意,onReceiveOrNull 是?個(gè)僅在?于不可空元素的通道上定義的擴(kuò)展函數(shù),以使關(guān)閉的通道與空值 之間不會(huì)出現(xiàn)意外的混亂。 現(xiàn)在有?個(gè)?成四次“Hello”字符串的 a 通道,和?個(gè)?成四次“World”字符串的 b 通道,我們在這 兩個(gè)通道上使?它:

val a = produce { repeat(4) { send("Hello $it") } } val b = produce { repeat(4) { send("World $it") } } repeat(8) { // 打印最早的?個(gè)結(jié)果 println(selectAorB(a, b)) } coroutineContext.cancelChildren()

這段代碼的結(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

有?個(gè)結(jié)果可以通過觀察得出。

?先,select 偏向于 第?個(gè)?句,當(dāng)可以同時(shí)選到多個(gè)?句時(shí),第?個(gè)?句將被選中。在這?,兩個(gè)通 道都在不斷地?成字符串,因此 a 通道作為 select 中的第?個(gè)?句獲勝。然?因?yàn)槲覀兪?的是?緩 沖通道,所以 a 在其調(diào)? send 時(shí)會(huì)不時(shí)地被掛起,進(jìn)? b 也有機(jī)會(huì)發(fā)送。

第?個(gè)觀察結(jié)果是,當(dāng)通道已經(jīng)關(guān)閉時(shí),會(huì)?即選擇 onReceiveOrNull。

Select 以發(fā)送

Select 表達(dá)式具有 onSend ?句,可以很好的與選擇的偏向特性結(jié)合使?。

我們來編寫?個(gè)整數(shù)?成器的?例,當(dāng)主通道上的消費(fèi)者?法跟上它時(shí),它會(huì)將值發(fā)送到 side 通道 上:

fun CoroutineScope.produceNumbers(side: SendChannel) = produce { for (num in 1..10) { // ?產(chǎn)從 1 到 10 的 10 個(gè)數(shù)值 delay(100) // 延遲 100 毫秒 select { onSend(num) {} // 發(fā)送到主通道 side.onSend(num) {} // 或者發(fā)送到 side 通道 } } }

消費(fèi)者將會(huì)?常緩慢,每個(gè)數(shù)值處理需要 250 毫秒:

val side = Channel() // 分配 side 通道 launch { // 對于 side 通道來說,這是?個(gè)很快的消費(fèi)者 side.consumeEach { println("Side channel has $it") } } produceNumbers(side).consumeEach { println("Consuming $it") delay(250) // 不要著急,讓我們正確消化消耗被發(fā)送來的數(shù)字 } println("Done consuming") coroutineContext.cancelChildren()

讓我們看看會(huì)發(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 consuming

Select 延遲值

延遲值可以使? onAwait ?句查詢。讓我們啟動(dòng)?個(gè)異步函數(shù),它在隨機(jī)的延遲后會(huì)延遲返回字符串:

fun CoroutineScope.asyncString(time: Int) = async { delay(time.toLong()) "Waited for $time ms" }

讓我們隨機(jī)啟動(dòng)?余個(gè)異步函數(shù),每個(gè)都延遲隨機(jī)的時(shí)間。

fun CoroutineScope.asyncStringsList(): List> { val random = Random(3) return List(12) { asyncString(random.nextInt(1000)) } }

現(xiàn)在 main 函數(shù)在等待第?個(gè)函數(shù)完成,并統(tǒng)計(jì)仍處于激活狀態(tài)的延遲值的數(shù)量。注意,我們在這?使? select 表達(dá)式事實(shí)上是作為?種 Kotlin DSL,所以我們可以?任意代碼為它提供?句。在這種情況 下,我們遍歷?個(gè)延遲值的隊(duì)列,并為每個(gè)延遲值提供 onAwait ?句的調(diào)?。

val list = asyncStringsList() val result = select { list.withIndex().forEach { (index, deferred) -> deferred.onAwait { answer -> "Deferred $index produced answer '$answer'" } } } println(result) val countActive = list.count { it.isActive } println("$countActive coroutines are still active")

該輸出如下:

Deferred 4 produced answer 'Waited for 128 ms' 11 coroutines are still active

在延遲值通道上切換

我們現(xiàn)在來編寫?個(gè)通道?產(chǎn)者函數(shù),它消費(fèi)?個(gè)產(chǎn)?延遲字符串的通道,并等待每個(gè)接收的延遲值, 但它只在下?個(gè)延遲值到達(dá)或者通道關(guān)閉之前處于運(yùn)?狀態(tài)。此?例將 onReceiveOrNull 和 onAwait ?句放在同?個(gè) select 中:

fun CoroutineScope.switchMapDeferreds(input: ReceiveChannel>) = produce { var current = input.receive() // 從第?個(gè)接收到的延遲值開始 while (isActive) { // 循環(huán)直到被取消或關(guān)閉 val next = select?> { // 從這個(gè) select 中返回下?個(gè)延遲值或 null input.onReceiveOrNull { update -> update // 替換下?個(gè)要等待的值 } current.onAwait { value -> send(value) // 發(fā)送當(dāng)前延遲?成的值 input.receiveOrNull() // 然后使?從輸?通道得到的下?個(gè)延遲值 } } if (next == null) { println("Channel was closed") break // 跳出循環(huán) } else { current = next } } }

為了測試它,我們將??個(gè)簡單的異步函數(shù),它在特定的延遲后返回特定的字符串:

fun CoroutineScope.asyncString(str: String, time: Long) = async { delay(time) str }

main 函數(shù)只是啟動(dòng)?個(gè)協(xié)程來打印 switchMapDeferreds 的結(jié)果并向它發(fā)送?些測試數(shù)據(jù):

val chan = Channel>() // 測試使?的通道 launch { // 啟動(dòng)打印協(xié)程 for (s in switchMapDeferreds(chan)) println(s) // 打印每個(gè)獲得的字符串 } chan.send(asyncString("BEGIN", 100)) delay(200) // 充?的時(shí)間來?產(chǎn) "BEGIN" chan.send(asyncString("Slow", 500)) delay(100) // 不充?的時(shí)間來?產(chǎn) "Slow" chan.send(asyncString("Replace", 100)) delay(500) // 在最后?個(gè)前給它?點(diǎn)時(shí)間 chan.send(asyncString("END", 500)) delay(1000) // 給執(zhí)??段時(shí)間 chan.close() // 關(guān)閉通道…… delay(500) // 然后等待?段時(shí)間來讓它結(jié)束

這段代碼的執(zhí)?結(jié)果:

BEGIN Replace END Channel was closed
分享標(biāo)題:kotlin協(xié)程——>select表達(dá)式(實(shí)驗(yàn)性的)-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://weahome.cn/article/jhhdd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部