1. コンセプト
これは選択式とも呼ばれ、複数の保留中の結果を同時に待機し、最も速く回復した値のみを使用できる一時停止関数です (つまり、複数の方法でデータを取得し、結果をより速く返す方法)。
select() が同時に到達した場合、部分式が先に書かれますが、ランダム (公平) にしたい場合は、 selectUnbiased() を使用して を置き換えます。
選択できるのはSelectClauseN関数の種類です。
public stop inline fun <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R |
パブリック シールド インターフェイス SelectBuilder<in R> { パブリック オペレーター fun SelectClause0.invoke(block: サスペンド () -> R) |
SelectClause0 | 対応するイベントには戻り値がありません。たとえば、job.onJoin。 |
選択条項 1 | 対応するイベントには戻り値があります。たとえば、defered.onAwait や channel.onReceive などです。 |
選択条項 2 | 対応するイベントには戻り値があります。さらに、追加のパラメータが必要です。たとえば、Channel.onSend() には 2 つのパラメータがあります。1 つ目は、送信する値を示す Channel データ型の値で、2 つ目は、送信が成功したときのコールバック関数です。 。 |
2. 使用する
async() を使用してコルーチンを開始する戻り値の型 Deferred では、SelectClause1 関数型の変数 onAwait が定義されています。その関数は、select( のサブステートメントとして使用される場合を除いて、await() と同じです。 )には、「同時に誰が待っているかを確認して待つ」「先に戻る」効果があります。他のことについても同様です。
2.1 複数の 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 複数の 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) //打印:最快的是Cache
}
2.3 複数チャネルの多重化.onReceive
パブリック インターフェイス SendChannel<in E> { public val onSend: SelectClause2<E, SendChannel<E>> //send() と同等 } |
パブリック インターフェイス ReceiveChannel<out E> { public val onReceive: SelectClause1<E> //等效receive() public stop fun acceptCatching(): ChannelResult<E> //等效receiveCatching() } //select() の OnReceive() は、閉じられたチャネルでの実行に失敗し、対応する select() が例外をスローします。チャネルを閉じるときに特定の操作を実行するには、onReceiveCatching() を使用します。 |
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已关闭:produceLocal" }
// produceRemote.onReceiveCatching { it.getOrNull() ?: "Channel已关闭:produceRemote " }
// }
println("结果更快的是:$result")
}