Coroutine Channels

버퍼링된 채널*1

지금까지 표시된 채널에는 버퍼가 없습니다. 버퍼링되지 않은 채널은 발신자와 수신자가 만날 때 값을 전송합니다. 이것을 랑데뷰라고도 합니다.*2 만약에 보내다먼저 실행 받다실행될 때까지 정지됩니다. 만약에 받다먼저 실행 보내다실행될 때까지 정지됩니다.

Channel() 팩토리 함수와 Produce 빌더는 선택적으로 버퍼 크기를 사용하여 크기를 결정합니다. 용량 매개변수를 가져옵니다. BlockingQueue is Buffer 과 유사함 용량버퍼가 가득 차면 발신자가 일시 중지*3 및 일시 중지*4 전에 여러 항목을 보낼 수 있습니다.

다음 코드의 동작을 살펴보겠습니다.

val channel = Channel<Int>(4) // create buffered channel
val sender = launch { // launch sender coroutine
    repeat(10) {
        println("Sending $it") // print before sending each element
        channel.send(it) // will suspend when buffer is full
    }
}
// don't receive anything... just wait....
delay(1000)
sender.cancel() // cancel sender coroutine

완전한 코드는 여기에서 찾을 수 있습니다

그건 용량4로 버퍼링된 채널을 사용하므로 전송이 5번 발행됩니다.

Sending 0
Sending 1
Sending 2
Sending 3
Sending 4

처음 4개의 항목이 버퍼에 추가되고 5번째 항목을 보내려고 하면 보낸 사람이 중지됩니다.


다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. 버퍼는 첫 번째 입력이 처리되지 않을 때 다음 입력을 저장하기 위한 메모리 공간입니다. 버퍼링된 채널은 첫 번째 입력이 아직 처리되지 않은 경우 전송하여 받은 다음 입력을 저장할 공간이 있는 채널입니다.

*2. 원문은 (일명 Rendezvous)이지만 이해를 돕기 위해 따로 번역했습니다. Rendezvous는 프랑스어로 ‘만나다’라는 뜻이다.

*삼. 용량 = 0이 기본값이지만 도착할 때마다 일시 중지됩니다.

*4. 원문은 막혀있지만 채널은 일시적으로 정지되어서 쉬는걸로 번역합니다.


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 채널 – 버퍼링된 채널

원본 텍스트의 최종 편집: 2022년 9월 28일


채널은 동일합니다

채널에서 전송 및 수신 작업은 여러 코루틴을 호출하는 순서를 따릅니다. 채널은 먼저 FIFO 구조로 제공됩니다. 받다호출하는 코루틴에는 하나의 멤버가 있습니다. 다음 예제에서는 두 개의 코루틴 “ping”과 “pong”이 함께 사용됩니다. 테이블 채널을 통해 “공” 개체를 받습니다.

data class Ball(var hits: Int)

fun main() = runBlocking {
    val table = Channel<Ball>() // a shared table
    launch { player("ping", table) }
    launch { player("pong", table) }
    table.send(Ball(0)) // serve the ball
    delay(1000) // delay 1 second
    coroutineContext.cancelChildren() // game over, cancel them
}

suspend fun player(name: String, table: Channel<Ball>) {
    for (ball in table) { // receive the ball in a loop
        ball.hits++
        println("$name $ball")
        delay(300) // wait a bit
        table.send(ball) // send the ball back
    }
}

완전한 코드는 여기에서 찾을 수 있습니다

“ping” 코루틴이 먼저 시작됩니다. “ping” 코루틴이 공을 다시 테이블로 보낸 후, “pong” 코루틴이 이미 듣고 있기 때문에 즉시 다시 받기 시작하더라도 “pong” 코루틴이 공을 받습니다.

ping Ball(hits=1)
pong Ball(hits=2)
ping Ball(hits=3)
pong Ball(hits=4)

사용하는 런처 유형으로 인해 채널이 부당하게 실행되는 경우가 있습니다. 자세한 내용은 이 문제확인 해보자 *하나


다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. 이 문제는 실제로 자주 발생합니다. 하나의 스레드에서 여러 코루틴을 실행할 때 문제가 있는 것 같습니다. 작업 중에 코루틴이 양보하면 스레드를 차지하는 코루틴이 먼저 실행됩니다. 따라서 스레드에서 여러 코루틴이 작동하는 경우 채널에 대한 수신을 먼저 수행하는 사람은 무작위가 됩니다. 그 이유는 수신 정지가 되지 않았기 때문입니다.


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 채널 – 코루틴 및 스레드 디버그

원본 텍스트의 최종 편집: 2022년 9월 28일


티커 채널

티커 채널은 채널이 마지막으로 사용된 후 일정 시간이 지나면 유닛을 생성하는 특별한 랑데부 채널입니다. 이것은 그 자체로는 쓸모가 없어 보일 수 있지만 복잡한 시간 기반 제품 파이프라인 블록을 구축하거나 윈도우*1 또는 시간 종속 처리에 유용합니다. 티커 채널을 선택하여 “온 틱” 작업을 수행할 수 있습니다.

이 채널을 만들기 위해 증권 시세 표시기 더 이상 항목을 받을 필요가 없음을 나타내기 위해 ReceiveChannel.cancel 메서드를 사용할 수 있습니다. 라는 팩토리 메서드를 사용합니다.

실제로 어떻게 작동하는지 봅시다:

fun main() = runBlocking<Unit> {
    val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
    var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
    println("Initial element is available immediately: $nextElement") // no initial delay

    nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
    println("Next element is not ready in 50 ms: $nextElement")

    nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
    println("Next element is ready in 100 ms: $nextElement")

    // Emulate large consumption delays
    println("Consumer pauses for 150ms")
    delay(150)
    // Next element is available immediately
    nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
    println("Next element is available immediately after large consumer delay: $nextElement")
    // Note that the pause between `receive` calls is taken into account and next element arrives faster
    nextElement = withTimeoutOrNull(60) { tickerChannel.receive() } 
    println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")

    tickerChannel.cancel() // indicate that no more elements are needed
}

완전한 코드는 여기에서 찾을 수 있습니다

그러면 다음 줄이 인쇄됩니다.

Initial element is available immediately: kotlin.Unit
Next element is not ready in 50 ms: null
Next element is ready in 100 ms: kotlin.Unit
Consumer pauses for 150ms
Next element is available immediately after large consumer delay: kotlin.Unit
Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit

티커는 소비자가 일시 중지하고 있음을 알고 있으며 기본 동작은 일시 중지가 발생하면 다음 항목의 생산을 지연시키는 것입니다. 특정 가격에 계속 만들어

선택적 모드 매개변수 TickerMode.FIXED_DELAY 두 요소 사이에 일정한 지연이 발생하도록 설정할 수 있습니다.


다음 내용은 독자의 이해를 돕기 위해 번역자가 추가한 내용입니다.

*하나. Windowing은 발신자로부터 승인을 받지 않고 데이터를 지속적으로 보내는 기술입니다.


이 문서는 공식 코루틴 문서를 번역한 것입니다.

원래의: 채널 – 티커 채널

원본 텍스트의 최종 편집: 2022년 9월 28일