首页 > 解决方案 > 所有生产者协程完成后如何关闭通道?

问题描述

考虑以下代码:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    launch {
        channel.send("A1")
        channel.send("A2")
        log("A done")
    }
    launch {
        channel.send("B1")
        log("B done")
    }
    launch {
        for (x in channel) {
            log(x)
        }
    }
}

fun log(message: Any?) {
    println("[${Thread.currentThread().name}] $message")
}

原始版本的接收器协程是这样的:

launch {
        repeat(3) {
            val x = channel.receive()
            log(x)
        }
    }

它预计频道中只有 3 条消息。如果我将其更改为第一个版本,那么我需要在所有生产者协程完成后关闭通道。我怎样才能做到这一点?

标签: kotlinkotlin-coroutineskotlinx.coroutines.channels

解决方案


一个可能的解决方案是创建一个等待所有人channel.send()完成的作业,然后调用channel.close()invokeOnCompletion作业的:

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.*

fun main() = runBlocking<Unit> {
    val channel = Channel<String>()
    launch {
      launch {
          channel.send("A1")
          channel.send("A2")
          log("A done")
      }
      launch {
          channel.send("B1")
          log("B done")
      }
    }.invokeOnCompletion {
        channel.close()
    }
    launch {
        for (x in channel) {
            log(x)
        }
    }
}

fun log(message: Any?) {
    println("[${Thread.currentThread().name}] $message")
}

推荐阅读