Kotlin Channels
A channel passes values from a sending coroutine to a receiving one. Each value moves across in send order and the receiver can wait for it.
A rendezvous channel in send order
The sender launches, sends the numbers one to three, and closes the channel. The receiving loop prints each number in send order.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
val channel = Channel<Int>()
val sender = launch {
for (x in 1..3) channel.send(x)
channel.close()
}
for (y in channel) {
println("got $y")
}
sender.join()
println("channel done")
}A buffered channel
This channel holds up to two values at a time. The loop still receives them in send order, and the sender is joined before the last line prints.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
val channel = Channel<Int>(2)
val sender = launch {
channel.send(10)
channel.send(20)
channel.close()
}
for (value in channel) {
println("got $value")
}
sender.join()
println("buffered done")
}Two senders joined in sequence
The first sender is joined before the second one starts, so every value is already placed in a fixed order. The parent then closes the channel and the loop drains it.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
val channel = Channel<Int>(4)
val first = launch {
channel.send(1)
channel.send(2)
}
first.join()
val second = launch {
channel.send(3)
channel.send(4)
}
second.join()
channel.close()
for (y in channel) {
println("got $y")
}
println("both senders done")
}Words through a channel
A channel carries strings in the same shape. The loop prints each word as it arrives and stops when the sender closes the channel.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
val channel = Channel<String>()
val sender = launch {
channel.send("alpha")
channel.send("beta")
channel.close()
}
for (word in channel) {
println("word $word")
}
sender.join()
println("words done")
}Example
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
fun main() = runBlocking {
val channel = Channel<Int>()
val sender = launch {
for (x in 1..4) channel.send(x * x)
channel.close()
}
var total = 0
for (value in channel) {
total += value
}
sender.join()
println("total: $total")
println("sum complete")
}Key points
- Channel builds a channel for one type of value.
- send hands a value to the channel and suspends until the value can move.
- A plain channel has no buffer, so a send waits for a receive.
- A buffered channel holds up to its capacity in values before a send must wait.
- A for loop over a channel receives values until the channel closes.
- close tells the receiver that no more values will come.
- Values arrive in the order they were sent.
In this example, the sender sends the squares one, four, nine, and sixteen, then closes the channel. The receiving loop adds each value to the total. The parent joins the sender and prints the finished sum.
Note
A receiver loop ends only after the channel is closed and drained.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Kotlin Playground
Exercise
What does close do to a channel?