0Pricing
Kotlin Academy · Урок

Типы каналов: Rendezvous, Buffered, Conflated, Unlimited

Выбирайте подходящий тип канала для используемой схемы взаимодействия.

«Типы каналов: Rendezvous, Buffered, Conflated, Unlimited» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Создание каналов

Создавайте каналы с помощью Channel<T>(capacity). Ёмкость определяет поведение буферизации и приостановки.

import kotlinx.coroutines.channels.Channel
val rendezvous = Channel<Int>()              // capacity 0
val buffered   = Channel<Int>(64)            // capacity 64
val unlimited  = Channel<Int>(Channel.UNLIMITED)
val conflated  = Channel<Int>(Channel.CONFLATED)
fun main() { println("Channel types created") }

Встречный канал (ёмкость = 0)

Канал по умолчанию. send приостанавливается, пока не будет готов получатель, а receive — пока отправитель не отправит значение. Они встречаются в одной точке.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>() // rendezvous
    launch {
        println("Sending...")
        ch.send(1)  // suspends until receiver is ready
        println("Sent")
    }
    delay(100)
    println("Receiving...")
    println(ch.receive())
}

Буферизованный канал

Буферизованный канал позволяет отправителю продолжать работу, не ожидая, пока буфер не заполнится. Когда буфер заполнен, send приостанавливается.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>(3) // buffer of 3
    launch {
        repeat(3) {
            println("Sending $it")
            ch.send(it) // does not suspend until buffer full
        }
        ch.close()
    }
    delay(500)
    for (v in ch) println("Got $v")
}

Буферизованный канал по умолчанию

Channel.BUFFERED использует ёмкость по умолчанию — 64. Это эквивалентно Channel(64).

import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.*
fun main() = runBlocking {
    val ch = Channel<String>(Channel.BUFFERED)
    println("Default buffer capacity is implementation-defined (~64)")
    ch.close()
}

Неограниченный канал

Channel.UNLIMITED никогда не приостанавливает отправителя: он буферизует все значения. Используйте его осторожно: память может расти без ограничений.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>(Channel.UNLIMITED)
    launch {
        repeat(1000) { ch.send(it) } // never suspends
        ch.close()
    }
    var sum = 0
    for (v in ch) sum += v
    println("Sum: $sum")
}

Канал с сохранением последнего значения

Channel.CONFLATED сохраняет только самое новое значение. Если новое значение поступает до получения предыдущего, старое отбрасывается.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>(Channel.CONFLATED)
    launch {
        repeat(5) { ch.send(it) } // 0..4 sent rapidly
        ch.close()
    }
    delay(50) // let all sends happen
    println("Received: ${ch.tryReceive().getOrNull()}") // likely 4 (last)
}

RENDEZVOUS и BUFFERED: синхронизация по времени

RENDEZVOUS синхронизирует производителя и потребителя. BUFFERED позволяет производителю работать с опережением, разделяя их временные характеристики.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>(Channel.BUFFERED)
    val t = System.currentTimeMillis()
    launch {
        repeat(5) { ch.send(it) } // fast — doesn't wait
        ch.close()
    }
    for (v in ch) { delay(100); println("$v at ${System.currentTimeMillis()-t}ms") }
}

Стратегия onBufferOverflow

С помощью Channel(capacity, onBufferOverflow) выберите поведение при заполнении буфера: приостановка по умолчанию, отбрасывание самых старых значений или отбрасывание самых новых.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ch = Channel<Int>(2, BufferOverflow.DROP_OLDEST)
    launch {
        repeat(5) { ch.trySend(it) } // 0,1,2,3,4 — buffer keeps newest 2
        ch.close()
    }
    for (v in ch) println(v) // likely 3 4
}

Выбор типа канала

Руководство: RENDEZVOUS — для тесной синхронизации; BUFFERED — для пропускной способности; CONFLATED — когда нужно только последнее значение, например состояние интерфейса; UNLIMITED — для журналирования событий, если потеря данных недопустима.

import kotlinx.coroutines.channels.Channel
// Use cases:
// RENDEZVOUS  — handshake between producer and consumer
// BUFFERED    — decouple I/O-heavy producer from slow consumer
// CONFLATED   — UI updates (only latest matters)
// UNLIMITED   — audit log (never drop)
fun main() { println("Choose based on your loss tolerance and timing needs") }

Каналы в конструкции выбора

select позволяет одновременно ожидать несколько каналов, выбирая первый готовый.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
fun main() = runBlocking {
    val a = produce { delay(100); send("from a") }
    val b = produce { delay(50);  send("from b") }
    val result = select<String> {
        a.onReceive { it }
        b.onReceive { it }
    }
    println(result) // "from b"
    coroutineContext.cancelChildren()
}

Канал-таймер

ticker(delay) создаёт канал, который выдаёт Unit каждые delay миллисекунд. Это полезно для повторяющегося опроса.

import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
fun main() = runBlocking {
    val ticker = ticker(delayMillis = 100, initialDelayMillis = 0)
    var count = 0
    for (tick in ticker) {
        println("Tick ${++count}")
        if (count == 3) { ticker.cancel(); break }
    }
}

Быстрая проверка

Какой тип канала сохраняет только самое новое значение?

Итоги

Встречный канал: синхронизация без буфера. Буферизованный канал: разделение временных характеристик. Канал с сохранением последнего значения: только новое значение, старые отбрасываются. Неограниченный канал: отправитель никогда не приостанавливается. Выбирайте тип с учётом допустимости потерь и требований к пропускной способности.

Часто задаваемые вопросы

Урок «Типы каналов: Rendezvous, Buffered, Conflated, Unlimited» бесплатный?

Да — полный текст урока «Типы каналов: Rendezvous, Buffered, Conflated, Unlimited» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Типы каналов: Rendezvous, Buffered, Conflated, Unlimited»?

Выбирайте подходящий тип канала для используемой схемы взаимодействия. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Типы каналов: Rendezvous, Buffered, Conflated, Unlimited»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы каналов: send, receive и close
  2. Типы каналов: Rendezvous, Buffered, Conflated, Unlimited
  3. Mutex и Semaphore для общего состояния
  4. Акторы и структурированное управление состоянием
← Назад к Kotlin Academy