Kotlin Channel 开箱即用

创建 & 容量/溢出

ini 复制代码
val ch = Channel<T>(
  capacity = Channel.BUFFERED,                 // 0(RENDEZVOUS) | BUFFERED(~64) | UNLIMITED | CONFLATED | N
  onBufferOverflow = BufferOverflow.SUSPEND    // SUSPEND | DROP_OLDEST | DROP_LATEST
)
  • RENDEZVOUS(0) :无缓冲,强背压;BUFFERED :小缓冲常用;UNLIMITED :慎用,易 OOM;CONFLATED:只保最新。
  • 选型:必达→SUSPEND只要最新→CONFLATED / DROP_OLDEST滑窗→N+DROP_OLDEST

发送 / 接收

kotlin 复制代码
suspend fun SendChannel<T>.send(x)         // 可能挂起(形成背压)
fun    SendChannel<T>.trySend(x)           // 非挂起,失败立即返回

suspend fun ReceiveChannel<T>.receive()    // 队列空会挂起
fun    ReceiveChannel<T>.tryReceive()      // 非挂起
for (e in ch) { /* 读到 close 且队列清空时自然结束 */ }

小技巧:先非阻塞、失败再挂起

kotlin 复制代码
suspend fun <T> SendChannel<T>.offerOrSend(x: T) {
  if (!trySend(x).isSuccess) send(x)
}

关闭 / 取消

  • close(cause?):不再接收新元素;已入队会被读完后结束(优雅收尾)。
  • cancel(cause?):立即终止,可能丢未读(紧急停机)。
  • 接收安全模板:
kotlin 复制代码
while (true) when (val r = ch.receiveCatching()) {
  is ChannelResult.Success -> handle(r.getOrNull()!!)
  is ChannelResult.Closed  -> break
}

常用并发模式

  • pipeline:多段 Channel 串联;每段容量=节流阀;重段可开 N 个 worker。
  • fan-in :多生产者→单通道;由协调者统一 close
  • fan-out :单生产者→多消费者(单播/竞争消费);要广播请用 SharedFlow。
  • actor:把共享状态封进单协程(邮箱 Channel),串行处理,免锁。

与 Flow / SharedFlow 互通

  • Channel → Flow:receiveAsFlow()(保留通道) / consumeAsFlow()(收完就 cancel)。

  • Flow → Channel:produceIn(scope) 或 .onEach { ch.send(it) }.launchIn(scope)。

  • Flow → SharedFlow/StateFlow:shareIn(...) / stateIn(...)。

  • SharedFlow ↔ Channel:shared.produceIn(scope)、launch { for (e in ch) shared.emit(e) }。

取舍:强背压 & 单播 → Channel多播 & 状态(最新值)→ SharedFlow/StateFlow拉式流水线/按需计算 → Flow


时间与选择器(速率/超时/心跳)

scss 复制代码
withTimeoutOrNull(300) { ch.receive() }    // 接收超时→null
withTimeout(200) { ch.send(cmd) }          // 发送限时(SUSPEND 满会超时)
val tick = ticker(200, 0)                  // 周期节拍器(ReceiveChannel<Unit>)
select {                                   // 谁先就选谁
  ch.onReceive { process(it) }
  tick.onReceive { flush() }
  onTimeout(3000) { markStale() }
}

调优与守则(超精简)

  • 容量从 64 起步:过大→高延迟;过小→抖动。
  • 高频但可丢中间:DROP_OLDEST / CONFLATED ;必须逐条:SUSPEND/RENDEZVOUS
  • 给持资源元素配 onUndeliveredElement 做释放。
  • 正常收尾:生产者 close → 消费者读干净 ;紧急:cancel
  • 别用 UNLIMITED 掩盖压力;监控队列长度(自增自减计数打点)。

迷你示例:UI 只要最新 + 限频

scss 复制代码
val latest = Channel<State>(Channel.CONFLATED)
launch(Dispatchers.Default) {
  while (isActive) latest.trySend(snapshot())
}
launch(Dispatchers.Main) {
  latest.receiveAsFlow().sample(200).collect(::render)
}
相关推荐
jiayong239 小时前
面试中遇到不熟悉问题的应对策略深度解析
面试·职场和发展
JAVA社区11 小时前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
哆来A梦没有口袋14 小时前
干货精讲 | 初级CSS面试高频考题
前端·css·面试
plainGeekDev14 小时前
Android运行时面试题:ART和JVM的区别都搞不清,别写精通了
jvm·面试·kotlin
Cosolar14 小时前
QwenPaw Agent 实现原理深度剖析
后端·面试·架构
贺国亚14 小时前
Agent 框架 · LangChain / LangGraph / AutoGen / CrewAI
面试
青山师15 小时前
动态规划算法深度解析:从状态转移方程到工业级优化
数据结构·算法·面试·动态规划·代理模式·java面试
zhangjw3415 小时前
第15篇:Java多线程零基础入门,进程线程、线程创建方式、线程生命周期、线程安全彻底吃透
java·开发语言·面试
Raink老师15 小时前
【AI面试临阵磨枪-086】什么是 AI Agent Skill?与传统 Function Calling、Tool 的区别?
人工智能·面试·职场和发展
李剑一16 小时前
小红书前端架构面试问的挺深入啊!面试官:Vue中组合式API与选项式API的设计权衡
vue.js·面试