๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

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?