Kotlin協程和在Android中的使用總結(六 通道Channel)

Channel

Deferred對象提供了一種在協程間傳遞值的簡便方式,Channel就是用於在協程間傳遞一個stream的值流。

Channel有點類似於BlockingQueue,不同的是,BlockingQueue的puttake 操作都是阻塞式的,而Channel的sendreceive都是可掛起的非阻塞式。

fun main() = runBlocking {
    val channel = Channel<Int>()
    launch {
        // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
        for (x in 1..5) channel.send(x * x)
    }
    // here we print five received integers:
    repeat(5) { println(channel.receive()) }
    println("Done!")
}

不同於Queue,channel可以被關閉,對於channel的關閉,我們可以使用close(),關閉前發射的值將仍然能在接收端收到,接收端通過for循環來遍歷接收到的值:

fun main() = runBlocking {
    val channel = Channel<Int>()
    launch {
        for (x in 1..5) channel.send(x * x)
        channel.close() // we're done sending
    }
    // here we print received values using `for` loop (until the channel is closed)
    for (y in channel) println(y)
    println("Done!")
}

在前面的博文中,我們介紹過當flow的發射過快,處理速度過慢時,可以採取相應的措施,可以通過produce返回一個ReceiveChannel,接收端通過consumeEach來遍歷,如下:

fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}

fun main() = runBlocking {
    val squares = produceSquares()
    squares.consumeEach { println(it) }
    println("Done!")
}

通過在CoroutineScope上定義擴展函數來創建協程實現結構化的併發,避免到處使用全局的協程Scope(GlobalScope),produce創建的協程,可以嵌套調用,如下:

fun main() = runBlocking {
    val numbers = produceNumbers() // produces integers from 1 and on
    val squares = square(numbers) // squares integers
    repeat(5) {
        println(squares.receive()) // print first five
    }
    println("Done!") // we are done
    coroutineContext.cancelChildren() // cancel children coroutines
}

fun CoroutineScope.produceNumbers() = produce<Int> {
    var x = 1
    while (true) send(x++) // infinite stream of integers starting from 1
}

fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
    for (x in numbers) send(x * x)
}

channel的扇出Fan-out和扇入Fan-in

Buffered channels 和 Ticker channels

多個協程可能會從同一個channel中接收值,這種情況稱爲Fan-out。
多個協程可能會向同一個channel發射值,這種情況稱爲Fan-in。
channel可以在定義時,設置一個緩衝的大小,類似於BlockingQueue。
考慮到這些場景使用不多,暫時不多做介紹,想了解的可以直接移步官網文檔:https://kotlinlang.org/docs/reference/coroutines/channels.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章