【问题标题】:Main function terminates before coroutines主函数在协程之前终止
【发布时间】:2018-10-12 16:05:33
【问题描述】:

我正在研究面向过程的编程课程中的一个项目。

我试图在协程中启动两个对象(生产者和消费者),然后让生产者消费。然后我告诉主函数等待协程完成 Job.join()。但是,这似乎不起作用。因为 invokeOnCompletion 函数是在生产/消费周期开始之前执行的。我在下面包含了代码和输出,并希望有任何输入。

这是面向过程编程课程中的项目。最终目标是生成多个对象实例并让它们使用通道进行通信。我以前从未在 kotlin 中编写过代码,也从未使用过协程。这甚至可能吗,还是我误解了协程?

class Producer(val idvar: Int) {
    var resource: Int = 10

    init {
        println("${idvar} was created.")
    }

    suspend fun getConsumed(channel: Channel<Int>) = produce<Int> {
        println("Someone is trying to consume me...")
        while(true) {
            channel.send(1)
            resource--
            println("I have ${resource} things left.")
            if(resource <= 0) {
                break
            }
            var sleep = ((Random().nextDouble())*1000).toLong()
            println("sleeping for ${sleep} ms")
            delay(1000)

        }
        println("I'm used up! I have ${resource} resources.")

    }
}

class Consumer() {
    var resource: Int = 0

    suspend fun consume(producer: Producer?, channel: Channel<Int>) = produce<Int> {
        println("Trying to consume producer: ${producer?.resource}")
        producer?.getConsumed(channel)
        while(true) {
            var recv = channel.receive()
            if(recv == 0) break
            resource += recv
        }
        println("Consumed in total: " + resource)
    }
}


fun main(args: Array<String>) = runBlocking<Unit> {

    val prodJob = launch {
        var prodObj: Producer = Producer(1)
        var consumObj: Consumer = Consumer()
        val chan = Channel<Int>()
        consumObj.consume(prodObj, chan)

        // Why does this println print before the above line is complete?
        println("Comsumption done.")
    }

    // invokeOnCompletion is executed before production/consumption is done?
    prodJob.invokeOnCompletion { println("Consumption is done?") }

    // Main could do other stuff here. 

    // Since prodJob is regarded as complete, main joins instantly.
    prodJob.join()
    println("Joined...")
}

输出是:

1 was created.
Comsumption done.
Trying to consume producer: 10
Consumption is done?
Someone is trying to consume me...
I have 9 things left.
sleeping for 310 ms
Joined...

【问题讨论】:

    标签: kotlin kotlinx.coroutines


    【解决方案1】:

    Consumer.consume()-方法不正确。删除 =produce&lt;Int&gt; 部分,它将起作用:

    suspend fun consume(producer: Producer?, channel: Channel<Int>) {
        println("Trying to consume producer: ${producer?.resource}")
        producer?.getConsumed(channel)
        while(true) {
            var recv = channel.receive()
            if(recv == 0) break
            resource += recv
        }
        println("Consumed in total: " + resource)
    }
    

    顺便说一句:Producer.getConsumed()-方法以错误的方式使用 =produce&lt;Int&gt;produce 创建一个从未使用过的新频道。由于produce-Method 的一些内部实现细节,它只是碰巧起作用。您应该使用launch 显式启动第二个协程。

    suspend fun getConsumed(channel: Channel<Int>) = launch {
        println("Someone is trying to consume me...")
        while(true) {
            channel.send(1)
            resource--
            println("I have ${resource} things left.")
            if(resource <= 0) {
                break
            }
            var sleep = ((Random().nextDouble())*1000).toLong()
            println("sleeping for ${sleep} ms")
            delay(1000)
    
        }
        println("I'm used up! I have ${resource} resources.")
    
    }
    

    【讨论】:

      猜你喜欢
      • 2018-11-24
      • 2014-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 2023-03-28
      • 2017-02-25
      • 1970-01-01
      相关资源
      最近更新 更多