异步构造生产者

时间:2019-06-03 16:25:27

标签: kotlin kotlin-coroutines

在某些情况下,我想异步地使用ReceiveChannel来构建produce,但是它挂了。这是一个简化的示例:

runBlocking {
    val deferredChannel = async {
        produce<String> { send("foo") }
    }

    val channel = deferredChannel.await()

    println("Got channel")

    val value = channel.receive()

    println("Got value $value")
}

都没有 println被点击。可能存在某种协程死锁,但我不清楚在何处/如何进行。

如何异步生成ReceiveChannel

编辑:如果我将produce更改为produce(capacity = 1),则可以使用,但是为什么呢?至少与生产者的能力无关,await()是否应该成功?如果我想保持容量= 0,又该怎么办?

1 个答案:

答案 0 :(得分:1)

  

如果我将生产方式更改为生产方式(产能= 1),这是可行的,但是为什么呢?不管生产者的能力如何,至少await()是否应该成功?

检查您调用的produce()方法上的docs,特别是容量参数上的docs和我们拥有的Channel(重点是我):

  

当容量为0 时-创建RendezvousChannel。 该频道根本没有任何缓冲区。仅当发送和接收调用在时间上相遇时,元素才从发送方转移到接收方(集合点),因此发送将挂起,直到另一个协程调用receive ,并且接收挂起,直到另一个协程调用发送。

这可能是它挂起的原因。您正在send线程上调用async,然后在await上调用它……但是,正如文档所说,还没有其他例程调用receive。 。,因此它将挂起,直到发生这种情况,然后挂起。

检查Channel上的同一链接,我们还看到为什么给它一个大于0的数字可以解决此问题(强调我的问题):

  

容量为正值,但小于UNLIMITED时,它将创建具有给定容量的基于阵列的通道。该通道具有固定容量的阵列缓冲区。 发件人仅在缓冲区已满时挂起,接收方仅在缓冲区为空时挂起