为什么具有无限缓冲通道的制作人不会从频道返回或返回无效数据?

时间:2018-02-22 09:17:01

标签: kotlin coroutine kotlin-coroutines

看看这个采用example from official Kotlin documentation

package com.example

import kotlinx.coroutines.experimental.channels.produce
import kotlinx.coroutines.experimental.runBlocking

fun main(args: Array<String>) = runBlocking {
    val producer = produce {
        for (x in 1..5) send(x)
    }

    for (i in producer) {
        println(i)
    }

    println("Done!")
}

如果我跑它会打印:

1
2
3
4
5
Done!

正如您在此处所看到的,默认情况下使用的是非缓冲通道。我们将其更改为缓冲频道:

package com.example

import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.channels.produce
import kotlinx.coroutines.experimental.runBlocking

fun main(args: Array<String>) = runBlocking {
    val producer = produce(capacity = Channel.UNLIMITED) {
        for (x in 1..5) send(x)
    }

    for (i in producer) {
        println(i)
    }

    println("Done!")
}

如果我多次运行它会打印出来:

1
Done!

2
Done!

或只是

Done!

我认为生产者会将数据放入缓冲通道,for循环将从中读取数据,直到它可以执行此操作(即,如果数据存在于通道或通道中,则它将被读取) 。因此,我认为for循环应该读取缓冲通道中的所有数据,即使它已关闭。我是对的吗?

任何人都可以解释为什么缓冲通道导致生产者的这种奇怪行为?是bug吗?

P.S。

  • kotlin-stdlib v.1.2.21(今天是最新版本)
  • kotlinx-coroutines-core v.0.22.2(今天是最新版本)

1 个答案:

答案 0 :(得分:1)

Kotlin团队已经确认这是一个错误,opened an issue就此回答了这个问题。

该问题的描述提到它只出现在produce构建器中并提供了一种解决方法,基本上是该方便构造的内联代码:

val producer = Channel<Int>(1)
launch(coroutineContext) {
    for(i in 1..2) {
        producer.send(i)
        println("Sent: $i")
    }
    producer.close()
}