Channels Flashcards

KOTLIN › Concurrency

What happens when you call send() on a full channel?
send() suspends the calling coroutine until there is room in the channel's buffer. It does not block the thread. For an unbuffered (rendezvous) channel, send() suspends until another coroutine calls receive().
What are the four channel capacity modes and how does each handle a full buffer?
RENDEZVOUS (capacity 0): send suspends until a receiver is ready. BUFFERED (default 64): send suspends when the buffer is full. CONFLATED: the buffer holds one element and overwrites it on each send, never suspending. UNLIMITED: the buffer grows without bound, send never suspends (risk of OOM).
What does produce {} return and what happens when its block finishes?
produce {} is a coroutine builder that returns a ReceiveChannel<T>. When the block completes (normally or by exception), the channel is automatically closed. It is the channel equivalent of a flow builder.
What is the difference between send() and trySend() on a channel?
send() is a suspend function that waits until the channel has capacity. trySend() is a non-suspending function that returns a ChannelResult immediately: success if the element was added, failure if the channel is full or closed. Use trySend() from non-suspending code like callbacks.
How does fan-out work with channels?
Multiple coroutines call receive() on the same channel. Each element is delivered to exactly one receiver (no duplication). The channel acts as a work queue, distributing items across consumers for parallel processing.
How does fan-in work with channels?
Multiple coroutines call send() on the same channel. All elements arrive in a single stream that one (or more) consumers can receive from. The channel merges multiple producers into one output.
Why are channels called 'hot' while flows are 'cold'?
A channel is hot because it exists and can buffer elements whether or not anyone is receiving. A flow is cold because it does nothing until collect() is called -- each collector triggers a fresh execution of the flow builder. Channels push eagerly; flows pull lazily.
What is channelFlow {} and when would you use it over a regular flow {}?
channelFlow {} creates a cold Flow backed by an internal channel. Unlike flow {}, the block runs in its own coroutine and can launch child coroutines that all call send(). Use it when you need concurrent emission from multiple coroutines inside a flow.
What happens when you close a channel and a coroutine tries to receive() from it?
After close(), any elements already in the buffer can still be received. Once the buffer is drained, receive() throws ClosedReceiveChannelException. The safer alternative is receiveCatching(), which returns a ChannelResult instead of throwing.

Back to Channels