0Pricing
Kotlin Academy · Lekcja

Typy Channel: Rendezvous, Buffered, Conflated, Unlimited

Wybierz właściwy typ kanału dla swojego wzorca komunikacji.

Typy Channel: Rendezvous, Buffered, Conflated, Unlimited to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Fabryka kanałów

Kanały należy tworzyć za pomocą Channel<T>(capacity). Pojemność określa buforowanie i zachowanie związane z zawieszaniem.

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") }

Kanał Rendezvous (capacity=0)

Kanał domyślny. send zawiesza wykonanie do momentu, gdy odbiorca będzie gotowy, a receive — do momentu, gdy nadawca wyśle wartość. Strony spotykają się w tym samym punkcie.

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())
}

Buforowany kanał

Buforowany kanał pozwala nadawcy kontynuować działanie bez oczekiwania, dopóki bufor się nie zapełni. Gdy jest pełny, send zawiesza wykonanie.

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

Channel.BUFFERED używa domyślnej pojemności (64). Jest to równoważne z 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()
}

Kanał o nieograniczonej pojemności

Channel.UNLIMITED nigdy nie zawiesza nadawcy — buforuje wszystkie wartości. Należy używać go ostrożnie: pamięć może rosnąć bez ograniczeń.

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")
}

Kanał conflated

Channel.CONFLATED zachowuje tylko najnowszą wartość. Jeśli nowa wartość nadejdzie przed odebraniem poprzedniej, stara zostanie odrzucona.

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)
}

Zależność czasowa RENDEZVOUS i BUFFERED

Rendezvous synchronizuje producenta i konsumenta. Buforowanie pozwala producentowi działać z wyprzedzeniem, rozdzielając ich tempo pracy.

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") }
}

Strategia onBufferOverflow

Za pomocą Channel(capacity, onBufferOverflow) można wybrać zachowanie po zapełnieniu bufora: SUSPEND (domyślne), DROP_OLDEST lub DROP_LATEST.

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
}

Wybór typu kanału

Wskazówki: Rendezvous do ścisłej synchronizacji; Buffered do zwiększania przepustowości; Conflated do przechowywania wyłącznie najnowszej wartości (np. stanu interfejsu użytkownika); Unlimited do rejestrowania zdarzeń, gdy utrata danych jest niedopuszczalna.

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") }

Kanał w select

select umożliwia jednoczesne oczekiwanie na wiele kanałów i wybiera pierwszy gotowy.

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()
}

Kanał ticker

ticker(delay) tworzy kanał, który emituje Unit co delay milisekund — jest to przydatne przy cyklicznym odpytywaniu.

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 }
    }
}

Szybkie sprawdzenie

Który typ kanału zachowuje tylko najnowszą wartość?

Podsumowanie

Rendezvous: synchronizacja bez bufora. Buffered: rozdzielenie tempa pracy. Conflated: tylko najnowsza wartość, starsze są odrzucane. Unlimited: nadawca nigdy nie jest zawieszany. Wyboru należy dokonać w zależności od dopuszczalnej utraty danych i wymaganej przepustowości.

Często zadawane pytania

Czy lekcja „Typy Channel: Rendezvous, Buffered, Conflated, Unlimited” jest bezpłatna?

Tak — pełny tekst „Typy Channel: Rendezvous, Buffered, Conflated, Unlimited” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Typy Channel: Rendezvous, Buffered, Conflated, Unlimited”?

Wybierz właściwy typ kanału dla swojego wzorca komunikacji. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Typy Channel: Rendezvous, Buffered, Conflated, Unlimited”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Podstawy Channel: send, receive i close
  2. Typy Channel: Rendezvous, Buffered, Conflated, Unlimited
  3. Mutex i Semaphore dla współdzielonego stanu
  4. Aktory i strukturalne zarządzanie stanem
← Powrót do Kotlin Academy