Select 표현식은 아직 실험적인 기능으로 동작이 변경되거나 하위 호환 제공이 안될 수도 있다.
select 표현식은 여러 중단 함수를 호출 후 그 결과를 동시에 대기할 수 있도록 해주고, 그 중 가장 먼저 완료된 결과를 이용할 수 있도록 해준다.
fun CoroutineScope.fizz() = produce<String> {
while (true) { // sends "Fizz" every 300 ms
delay(300)
send("Fizz")
}
}
fun CoroutineScope.buzz() = produce<String> {
while (true) { // sends "Buzz!" every 500 ms
delay(500)
send("Buzz!")
}
}
fun main(args: Array<String>) = runBlocking<Unit> {
val fizz = fizz()
val buzz = buzz()
repeat(7) {
selectFizzBuzz(fizz, buzz)
}
coroutineContext.cancelChildren() // cancel fizz & buzz coroutines
}
suspend fun selectFizzBuzz(fizz: ReceiveChannel<String>, buzz: ReceiveChannel<String>) {
select<Unit> {
// <Unit> means that this select expression does not produce any result
fizz.onReceive { value ->
// this is the first select clause
println("fizz -> '$value'")
}
buzz.onReceive { value ->
// this is the second select clause
println("buzz -> '$value'")
}
}
}
fizz -> ‘Fizz’
buzz -> ‘Buzz!’
fizz -> ‘Fizz’
fizz -> ‘Fizz’
buzz -> ‘Buzz!’
fizz -> ‘Fizz’
buzz -> ‘Buzz!’
select 표현식 내부에 onReceive
함수를 통해 여러 채널에서 동시에 수신 받도록 구현할 수 있다.
select 블록 안에 onReceive
함수는 채널이 닫히면 예외를 전달하고 실패함
→ 이 경우 onReceiveCatching
함수 사용가능
onReceiveCatching
결과를 곧바로 반환위의 코드를 보면 a 채널이 우선 순위를 가짐에도 b 채널에 send가 실행됨
→ 채널은 기본적으로 버퍼가 0이기 때문에 send 사이에 중단이 생김
채널에 버퍼를 줄 경우 a 채널에만 send 실행됨을 볼 수 있음