Channel
Deferred對象提供了一種在協程間傳遞值的簡便方式,Channel就是用於在協程間傳遞一個stream的值流。
Channel有點類似於BlockingQueue,不同的是,BlockingQueue的put 和take 操作都是阻塞式的,而Channel的send和receive都是可掛起的非阻塞式。
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