분류 전체보기
Coroutine Channels 3편 - Fan-out과 Fan-in : Channel이 얼마나 많은 출력, 입력을 만들 수 있는지 알아보기
Fan-out*1 복수의 Coroutine은 같은 채널로부터 수신하면서, 그들간에 작업을 분산할 수 있다. 1초에 10개의 숫자를 주기적으로 정수를 생성하는 생산자 Coroutine으로 시작하자 : fun CoroutineScope.produceNumbers() = produce { var x = 1 // start from 1 while (true) { send(x++) // produce next delay(100) // wait 0.1s } } 그러면 우리는 몇개의 프로세서 Coroutine*2을 가질 수 있다. 이 예에서 프로세서 Coroutine은 그들의 id와 받은 숫자를 출력한다. fun CoroutineScope.launchProcessor(id: Int, channel: ReceiveCh..
Coroutine Channels 2편 - Channel로 파이프라인 만들기, 파이프라인으로 소수 만들기
Channel로 파이프라인 만들기 파이프라인은 하나의 Coroutine이 값의 스트림을 생성하는 것을 뜻한다. 값의 스트림은 무한할 수도 있다. fun CoroutineScope.produceNumbers() = produce { var x = 1 while (true) send(x++) // infinite stream of integers starting from 1 } 그리고 다른 Coroutine이나 Coroutines 들이 그 스트림을 소비하고, 작업을 수행하고, 다른 결과를 생성한다. 아래의 예시에서 숫자들은 단순히 제곱된다. fun CoroutineScope.square(numbers: ReceiveChannel): ReceiveChannel = produce { for (x in numbe..
Coroutine Channels 1편 - Channel이란 무엇인가, Channel 닫기, Channel 반복적으로 수신하기, Producer로 Channel 만들기
Deffered 값은 두 코루틴 사이에 단일 값을 전달하는데 편리한 방법을 제공한다. Channel은 값의 스트림을 전달하는 방법을 제공한다. Channel이란 무엇인가? Channel은 개념적으로 BlockingQueue와 매우 유사하다. 주요한 다른점은 블로킹 연산인 put 대신 일시중단 연산인 send를 가지고, 블로킹 연산인 take 대신 일시중단 연산인 receive를 가진다는 점이다.*1 val channel = Channel() launch { // this might be heavy CPU-consuming computation or async logic, we'll just send five squares for (x in 1..5) channel.send(x * x) } // here ..
Coroutines Flow 8편 - Flow 실행하기, Flow와 Reactive Stream
Flow 실행하기 일부 소스에서 오는 비동기 이벤트를 표현하기 위해 flow를 사용하기 쉽다. 이런 경우, 들어오는 이벤트에 대한 반응을 코드로 등록하고 이후의 작업을 계속해서 수행하도록 하는 addEventListener() 함수와 비슷한 역할을 하는 것이 필요하다. 이 역할을 onEach 연산자가 해줄 수 있다. 그러나, onEach는 중간 연산자이다. Flow를 수집하기 위해서는 터미널 연산자 또한 필요하다. 그렇지 않으면 onEach만을 호출하는 것만으로는 효과가 없다. 만약 onEach 이후에 collect 터미널 연산자를 사용하면, 이후의 코드는 Flow가 수집될 때까지 기다릴 것이다 : // Imitate a flow of events fun events(): Flow = (1..3).asF..
Coroutines Flow 7편 - Flow 수집 완료 처리하기, Flow 명령적으로 다루기 vs 선언적으로 다루기
Flow 수집 완료 처리하기 flow 수집이 완료되면(정상적으로 혹은 예외가 발생되어서), 완료에 따른 동작을 실행해야 할 수 있다. 이미 알 수도 있듯이, 이는 명령적인 방식 혹은 선언적인 방식 두가지 방식으로 실행될 수 있다. 명령적인 finally 블록 try/catch에 더해서, 수집기는 collect 동작이 완료됨에 따라 동작을 실행하는 finally 블록을 사용할 수 있다. fun simple(): Flow = (1..3).asFlow() fun main() = runBlocking { try { simple().collect { value -> println(value) } } finally { println("Done") } } 📌 전체 코드는 이곳에서 확인할 수 있습니다. 이 코드는 si..