Сопрограммы Kotlin — Multiplex Select()

1. Концепция

        Это также называемое выражением выбора. Это функция приостановки, которая может одновременно ожидать несколько ожидающих результатов и использовать только то значение, которое восстанавливается быстрее всего (то есть получать данные несколькими способами, в зависимости от того, какой из них возвращает результат быстрее).

        Когда одновременно будет достигнут метод select(), подвыражение будет записано первым. Если вы хотите, чтобы оно было случайным (справедливым), используйте selectUnbiased() для замены .

        Что можно выбрать, так это тип функции SelectClauseN.

public приостановить встроенное развлечение <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R 

общедоступный запечатанный интерфейс SelectBuilder<in R> {

        публичный оператор fun SelectClause0.invoke(block: suspend () -> R)
        публичный оператор fun <Q> SelectClause1<Q>.invoke(block: suspend (Q) -> R)
        публичный оператор fun <P, Q> SelectClause2<P , Q>.invoke(параметр: P, блок: приостановить (Q) -> R)
        открытый оператор fun <P, Q> SelectClause2<P?, Q>.invoke(блок: приостановить (Q) -> R): Единица измерения = вызвать (ноль, блок)
}

SelectClause0 Соответствующее событие не имеет возвращаемого значения. Например, job.onJoin.
SelectClause1 Соответствующее событие имеет возвращаемое значение. Например, deffered.onAwait иchannel.onReceive.
SelectClause2 Соответствующее событие имеет возвращаемое значение. Кроме того, требуется дополнительный параметр. Например, Channel.onSend() имеет два параметра. Первый — это значение типа данных Channel, указывающее значение, которое необходимо отправить, а второй — функция обратного вызова при успешной отправке. .

2. Используйте

В возвращаемом типе Deferred, который использует async() для запуска сопрограммы, определена переменная onAwait типа функции SelectClause1. Ее функция аналогична await(), за исключением того, что она используется как подоператор в select( ), он имеет функцию «ожидания, чтобы увидеть, кто ждет в то же время». Эффект «Сначала вернись». То же самое касается и других вещей.

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

общедоступный интерфейс 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()

        публичная приостановка развлечения getCatching(): ChannelResult<E> //等效receiveCatching()

}

//OnReceive() в select() не сможет выполниться на закрытом канале и приведет к тому, что соответствующий 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")
}

Guess you like

Origin blog.csdn.net/HugMua/article/details/132613352