select 함수
가장 먼저 완료되는 코루틴의 결과를 기다리는 함수
지연되는 값 선택
suspend fun main(): Unit = coroutineScope {
println(askMultipleForData())
}
val scope = CoroutineScope(SupervisorJob())
suspend fun askMultipleForData(): String {
val data1 = scope.async { requestData1() }
val data2 = scope.async { requestData2() }
return select {
data1.onAwait { it }
data2.onAwait { it }
}
}
suspend fun requestData1(): String {
delay(10_000)
return "Data1"
}
suspend fun requestData2(): String {
delay(1000)
return "Data2"
}
// 결과 (1초후에)
Data2
코루틴끼리 경합
suspend fun main(): Unit = coroutineScope {
println(askMultipleForData())
}
suspend fun askMultipleForData(): String = coroutineScope {
select<String> {
async { requestData1() }.onAwait { it }
async { requestData2() }.onAwait { it }
}.also { coroutineContext.cancelChildren() }
}
// 결과 (1초 후)
Data2
채널에서 값 선택하기
select는 여러 개의 채널 중 버퍼에 남은 공간이 있는 채널을 확인해 데이터를 보내거나
이용 가능한 원소가 있는 채널로부터 데이터를 받을 수 있는지 확인 가능
select 에서 사용하는 함수
onReceive
채널이 값을 가지고 있을 때 선택된다. select는 람다식의 결과값 반환
onReceiveCatching
채널이 값을 가지고 있거나 닫혔을 때 선택된다. ChannelResult 받아 사용. select는 람다식의 결과값 반환
onSend
채널의 버퍼에 공간이 있을 때 선택된다. 채널에 값을 보낸 뒤 채널의 참조값으로 람다식 수행. select는 Unit 반환
onReceive 사용
fun main() = runBlocking {
val channel1 = produceString("channel1", 210L)
val channel2 = produceString("channel2", 500L)
repeat(7) {
select {
channel1.onReceive {
println("From channel1: $it")
}
channel2.onReceive {
println("From channel2: $it")
}
}
}
coroutineContext.cancelChildren()
}
suspend fun CoroutineScope.produceString(
s: String,
time: Long
) = produce {
while (true) {
delay(time)
send(s)
}
}
// 결과
From channel1: channel1
From channel1: channel1
From channel2: channel2
From channel1: channel1
From channel1: channel1
From channel2: channel2
From channel1: channel1
onSend 호출
(버퍼에 공간이 있는 채널을 선택해 데이터 전송)
fun main(): Unit = runBlocking {
val channel1 = Channel<Char>(capacity = 2)
val channel2 = Channel<Char>(capacity = 2)
// 값 send
launch {
for (c in 'A'..'H') {
delay(400)
select<Unit> {
channel1.onSend(c) { println("Sent $c to 1") }
channel2.onSend(c) { println("Sent $c to 2") }
}
}
}
// 값 receive
launch {
while (true) {
delay(1000)
val c = select<String> {
channel1.onReceive { "$it from 1"}
channel2.onReceive { "$it from 2"}
}
println("Received $c")
}
}
}
// 결과
Sent A to 1
Sent B to 1
Received A from 1
Sent C to 1
Sent D to 2
Received B from 1
Sent E to 1
Sent F to 2
Received C from 1
Sent G to 1
Received E from 1
Sent H to 1
Received G from 1
Received H from 1
Received D from 2
Received F from 2
'코루틴' 카테고리의 다른 글
[코루틴] Flow란 - (1) (0) | 2024.11.24 |
---|---|
[코루틴] 핫 데이터와 콜드 데이터 (0) | 2024.11.23 |
[코루틴] Channel (채널) (0) | 2024.11.18 |
[코루틴] 코루틴의 동작 방식 (0) | 2024.09.29 |
[코루틴] 무제한 디스패처 (Unconfined Dispatcher) (0) | 2024.09.29 |