一、概念
? ? ? ? 又叫選擇表達式,是一個掛起函數(shù),可以同時等待多個掛起結(jié)果,只取用最快恢復(fù)的那個值(即多種方式獲取數(shù)據(jù),哪個更快返回結(jié)果就用哪個)。
????????同時到達 select() 會優(yōu)先選擇先寫子表達式,想隨機(公平)的話使用 selectUnbiased() 替換?。
????????能被選擇的都是?SelectClauseN?函數(shù)類型。
public suspend inline fun <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R? |
public sealed interface SelectBuilder<in R> { ????????public operator fun SelectClause0.invoke(block: suspend () -> R) |
SelectClause0 | 對應(yīng)事件沒有返回值。例如 job.onJoin。 |
SelectClause1 | 對應(yīng)事件有返回值。例如 deffered.onAwait 和 channel.onReceive。 |
SelectClause2 | 對應(yīng)事件有返回值。此外還需要一個額外的參數(shù),例如 Channel.onSend() 有兩個參數(shù),第一個是 Channel 數(shù)據(jù)類型的值表示即將發(fā)送的值,第二個是發(fā)送成功時的回調(diào)函數(shù)。 |
二、使用
在使用 async() 啟動協(xié)程的返回類型 Deferred 中,定義了 SelectClause1?函數(shù)類型的變量 onAwait,其作用和 await()?一樣,只是當(dāng)其在 select() 中作為子語句時,具有“同時等待看誰最先返回”的效果。同理其它。
2.1 復(fù)用多個 job.onJoin
fun main() = runBlocking<Unit> {
val job1 = launch {
delay(100)
println("job 1")
}
val job2 = launch {
delay(10)
println("job 2")
}
select {
job1.onJoin { println("job 1 更快") }
job2.onJoin { println("job 2 更快") }
}
delay(1000)
}
//打?。?//job 2
//job 2 更快
//job 1
2.2 復(fù)用多個?deffered.onAwait
public interface Deferred<out T> : Job { ????????public val onAwait: SelectClause1<T>? ? ? ? //等效await() } |
fun main() = runBlocking {
val defferedCache = async {
delay(10)
"Cache"
}
val defferedLocal = async {
delay(100)
"Local"
}
val defferedRemote = async {
delay(1000)
"Remote"
}
val result = select {
defferedCache.onAwait { println("最快的是$it") }
defferedLocal.onAwait { println("最快的是$it") }
defferedRemote.onAwait { println("最快的是$it") }
}
delay(2000)
println(result) //打?。鹤羁斓氖荂ache
}
2.3 復(fù)用多個 channel.onReceive
public interface SendChannel<in E> { ????????public val onSend: SelectClause2<E, SendChannel<E>>? ? ? ? //等效send() }文章來源:http://www.zghlxwxcb.cn/news/detail-693237.html |
public interface ReceiveChannel<out E> { ????????public val onReceive: SelectClause1<E>? ? ? ? //等效receive() ????????public suspend fun receiveCatching(): ChannelResult<E>? ? ? ? //等效receiveCatching() } //select() 中的 onReceive() 在已經(jīng)關(guān)閉的通道執(zhí)行會發(fā)生失敗,并導(dǎo)致相應(yīng)的 select() 拋出異常,使用 onReceiveCatching() 在關(guān)閉通道時執(zhí)行特定操作。文章來源地址http://www.zghlxwxcb.cn/news/detail-693237.html |
suspend fun getDataFromLocal() = withContext(Dispatchers.IO) { "Local" }
suspend fun getDataFromRemote() = withContext(Dispatchers.IO) { "Remote" }
@OptIn(ExperimentalCoroutinesApi::class)
fun main() = runBlocking {
val produceLocal = produce { send(getDataFromLocal()) }
val produceRemote = produce { send(getDataFromRemote()) }
val result = select {
produceLocal.onReceive { it }
produceRemote.onReceive { it }
}
// val result = select {
// produceLocal.onReceiveCatching { it.getOrNull() ?: "Channel已關(guān)閉:produceLocal" }
// produceRemote.onReceiveCatching { it.getOrNull() ?: "Channel已關(guān)閉:produceRemote " }
// }
println("結(jié)果更快的是:$result")
}
到了這里,關(guān)于Kotlin 協(xié)程 - 多路復(fù)用 select()的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!