Kotlin-协程通道-它们会阻塞调用线程吗?

时间:2019-05-18 06:42:30

标签: kotlin-coroutines

我知道通道是实验性的,我们可以认为通道与Java中的阻塞队列相同。话虽如此,让我们看一下这个简单的block of code

fun main(args: Array<String>) {

    val channel = Channel<Int>()
    GlobalScope.launch {
        for (x in 1..50000) {
            println("from channel $x")
            channel.send(x * x)
        }
    }
    // here we print five received integers:
    runBlocking {repeat(5) { println(channel.receive()) }}
    println("Done!")

}

我想知道其余整数会发生什么。查看运行此命令的输出:

 from channel 1
1
from channel 2
from channel 3
4
9
from channel 4
from channel 5
16
from channel 6
25
Done!

为什么没有打印所有50000个整数?我在全球范围内都有它。因此此行:println("from channel $x")应该被调用50000次。为什么没有呢?

2 个答案:

答案 0 :(得分:1)

send是一个暂停函数,如果在另一端没有人要接收/出队,则阻塞协程(不是线程)。这就是协程世界中支持背压的方式。您的runBlocking仅重复进行5次迭代,然后退出主退出窗口。

答案 1 :(得分:1)

频道内部队列的默认容量为1。这是所谓的 rendezvous 频道,因为生产者和消费者协程必须见面才能交换商品。由于您只消耗五件商品,因此制作人只能生产其中五件商品,并在交付第六件商品之前将其暂停,从而完成整个程序。

因此,这是您程序的修改,可以打印所有50,000个项目:

fun main() {
    val channel = Channel<Int>(Channel.UNLIMITED)
    GlobalScope.launch {
        for (x in 1..50000) {
            println("from channel $x")
            channel.send(x * x)
        }
    }
    Thread.sleep(1000)
    println("Done!")
}

请注意,这次无需消耗任何一种。