Kotlin Channel

280 阅读1分钟

Kotlin 的 Channel 是协程间通信的核心组件,本质上是一个并发安全的队列,支持生产-消费模式的数据传输。以下是其核心特性的结构化解析:


一、基础概念

  1. 管道模型
    Channel 表现为发送方(send)与接收方(receive)之间的通信管道,数据按顺序传递且每个元素仅被一个接收者消费36。默认实现为无缓冲通道(RENDEZVOUS),需发送和接收协程同时就绪才能完成传输4。
  2. 非阻塞挂起特性
    BlockingQueue 不同,sendreceive 是挂起函数:当缓冲区满或空时自动挂起协程,而非阻塞线程67。

二、基本使用

// 创建 Channel
val channel = Channel<Int>()

// 生产者协程
launch {
    repeat(10) {
        delay(100)
        channel.send(it) // 发送数据
    }
    channel.close() // 关闭通道
}

// 消费者协程
launch {
    for (element in channel) { // 通过迭代接收
        println("Received: $element")
    }
}

三、类型与容量配置

  1. 缓冲策略
    通过 Channel(capacity) 构造函数指定缓冲区容量及溢出策略:

    • RENDEZVOUS‌(默认):无缓冲,需发送/接收同时就绪4。
    • UNLIMITED‌:无界缓冲区,send 永不挂起7。
    • CONFLATED‌:仅保留最新元素,自动丢弃旧值4。
    • BUFFERED‌:固定大小缓冲区(默认 64)7。
  2. 溢出处理
    通过 onBufferOverflow 参数定义缓冲区满时的行为:

    • SUSPEND(默认):挂起发送方4。
    • DROP_OLDEST:丢弃最旧元素4。
    • DROP_LATEST:丢弃最新元素4。

四、高级特性

  1. 关闭与异常处理

    • 调用 close() 关闭通道,触发接收端的迭代终止4。
    • 通过 onUndeliveredElement 回调处理未投递元素的清理逻辑(如资源释放)4。
  2. 多接收者竞争
    单个元素仅能被一个接收者消费,多个接收者会形成竞争关系4。示例中两个接收者可能交替获取不同元素。


五、与 Flow 的对比

特性ChannelFlow
通信模式点对点(单播)广播(冷流)
生命周期主动管理(需手动关闭)自动取消
适用场景协程间实时通信数据流处理(如网络响应)

六、典型应用场景

  1. 生产者-消费者模式‌:如后台任务与 UI 更新的解耦。
  2. 事件总线‌:通过 BroadcastChannel(已废弃,推荐 SharedFlow)实现多订阅6。
  3. 多路复用‌:结合 select 实现多个 Channel 的优先级处理8。

七、案例

fun main():Unit = runBlocking {

    val channel = Channel<Int>()

    launch {
        (1..1000) .forEach{
            delay(2000)
            channel.send(it)
            println("生产一个:$it")
        }
    }

    launch {
        (1..1000) .forEach{
            delay(2000)
            var it = channel.receive()
            println("消费一个:$it")
        }
    }
    //channel 是一个队列,默认缓冲区是0
    //如果缓冲区满了,如果recevice 没有消费,此时send会挂起,直到receive消费掉,send 再次恢复再生产一个

}

八、注意事项

  1. 资源泄漏‌:未关闭的 Channel 可能导致协程无法结束4。
  2. 性能调优‌:合理选择缓冲区大小与溢出策略,避免频繁挂起或数据丢失