3

从官方 Kotlin 文档中查看这个采用的示例:

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循环应该从缓冲通道中读取所有数据,即使它已关闭。我对吗?

谁能解释一下为什么缓冲通道会导致生产者的这种奇怪行为?是虫子吗?

附言

  • kotlin-stdlib v.1.2.21(今天是最后一个版本)
  • kotlinx-coroutines-core v.0.22.2(今天是最后一个版本)
4

1 回答 1

2

Kotlin 团队已确认这是一个错误,并针对此问题为其打开了一个问题。

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

val producer = Channel<Int>(1)
launch(coroutineContext) {
    for(i in 1..2) {
        producer.send(i)
        println("Sent: $i")
    }
    producer.close()
}
于 2018-02-22T12:25:11.973 回答