Kotlin の Channel(チャネル) は、コルーチン間で安全にデータを受け渡すための “通信・キュー” の抽象化です。
しばしば Flow と比較されますが、Channel は
- 状態やストリーム表現ではなく
- 並行処理における通信・調停のための低レベル構造
という位置づけになります。
目次
Channelの本質
Channelは「キュー + 同期ポイント」
Channelは次の2つを同時に満たします。
- 値を一時的に保持できる(キュー)
- 送信と受信を suspend によって自然に同期できる
つまり、
- ロックを書かず
- スレッドをブロックせず
- コルーチン同士が協調して処理を進められる
というのが最大の価値です。
Producer Coroutine ──▶ Channel ──▶ Consumer Coroutine
基本構文と挙動
Channelの生成
val channel = Channel<Int>()
これは Rendezvous Channel(容量0) を生成します。
- 値を「溜めない」
- 送信と受信が出会った瞬間に値が渡る
送信(send)
launch {
channel.send(1)
}
sendは suspend関数- 受信側がいなければ コルーチンが停止(suspend)
受信(receive)
launch {
val value = channel.receive()
}
- 値が来るまで suspend
- スレッドは止まらない
Channelは「ブロック」しない
Java の BlockingQueue との決定的な違いです。
| 項目 | BlockingQueue | Channel |
|---|---|---|
| 待機 | スレッドをブロック | コルーチンをサスペンド |
| スケール | 悪い | 非常に良い |
| 非同期設計 | 困難 | 前提 |
これにより、Channel は 大量の並行処理でも破綻しにくい構造になります。
Channelの種類(容量設計がすべて)
Rendezvous Channel
Channel<Int>()
- 送信と受信が 必ず同期
- バックプレッシャーが自然にかかる
向いている用途
- 生産と消費の速度を揃えたい
- 処理の順序・整合性が重要
Buffered Channel
Channel<Int>(capacity = 10)
- 最大10件まで保持
- 超えると
sendが suspend
向いている用途
- 一時的な負荷の偏りを吸収
- IO待ち・ネットワーク処理
Conflated Channel
Channel<Int>(Channel.CONFLATED)
- 常に最新1件のみ保持
- 古い値は破棄される
注意点
- StateFlow の代替ではない
- 「状態管理」ではなく「通信の簡略化」
向いている用途
- 進捗率
- センサー値
- UIに渡す“最新情報だけ”の通知
Unlimited Channel
Channel<Int>(Channel.UNLIMITED)
sendが基本的に suspend しない- バックプレッシャーが消失
⚠ 注意
- メモリ枯渇の危険
- 明確な理由がない限り避ける
受信の基本形:forループ
launch {
for (value in channel) {
println(value)
}
}
close()されるまで受信し続ける- close後は 自然終了
receive()を直接呼ぶより安全
Channelのcloseとは何か
channel.close()
- これ以上 send できない
- すでに送られた値はすべて受信される
- forループが終了する
※ close後に send すると例外になるため、実務では 送信側の責務を明確に分けるのが重要です。
Channelが得意な典型パターン
Producer–Consumer
fun CoroutineScope.producer() = produce {
repeat(5) {
send(it)
}
}
produceは Channel を返す- 生産と消費を明確に分離できる
Fan-out
repeat(3) {
launch {
for (value in channel) {
println("Worker $it got $value")
}
}
}
重要な性質
- 1つの値は 1つのConsumerにのみ届く
- ブロードキャストではない
→ 並列ワーカー処理に最適
Fan-in
val channel = Channel<Int>()
repeat(3) {
launch {
channel.send(it)
}
}
- 複数Producer → 1 Consumer
- 集約処理・ログ収集など
ChannelとFlowの正確な違い
Channel
- hot
- 通信・キューのモデル
- 値は基本的に 1回消費
- 並行処理・バックプレッシャー制御が主役
Flow(cold)
- collect されて初めて流れる
- 宣言的・変換に強い
- データストリームの表現向き
SharedFlow / StateFlow(hot)
- 複数購読を前提
- イベント配信 / 状態管理向き
- UI層ではこちらが主流
よくある誤用と注意点
Channelで状態管理しようとする
→ StateFlowの役割
UIイベントを雑にChannelで流す
→ 取りこぼし・二重処理の原因
→ SharedFlow のほうが安全なケースが多い
closeを設計せず使う
→ 無限待機・リークの原因
実務での判断基準
- 並行処理・ワーカー制御・キュー → Channel
- 状態の保持と購読 → StateFlow
- イベント配信(複数購読) → SharedFlow
- データ変換パイプライン → Flow
まとめ
- Channelは コルーチン間通信の基礎構造
- send / receive は suspend で自然な同期
- 容量設計が最重要
- ブロードキャスト用途ではない
- Flow / StateFlow と役割を混同しないことが最大のポイント
以上、KotlinのChannelについてでした。
最後までお読みいただき、ありがとうございました。









