직장에서 kotlin Coroutines
패키지 아래에 매우 강력한 API가 많이 있다는 것을 발견했습니다. 이 기사에서는 주로 select
함수 에 대해 이야기하겠습니다.
1. 선택 기능은 무엇인가요?
이런 시나리오를 상상해 보세요. 프로그램 응용 프로그램에서 비즈니스 로직을 구현하려면 여러 가지 방법으로 구현할 수 있지만 결과를 얻으려면 가장 빠른 방법만 필요합니다. 이때 함수를 사용할 수 있습니다 select
. 아직 무슨 뜻인지 모르신다면 아래 그림을 보시면 됩니다.
![](https://img-blog.csdnimg.cn/img_convert/8db0b4ada0881bed2d593800cdc2e2c6.jpeg)
금은 최근 비교적 비싸졌습니다. 우리 클라이언트는 실시간으로 금 가격을 쿼리해야 합니다. 이제 NetEase 서버와 Toutiao 서버는 동시에 쿼리 인터페이스를 제공합니다. 이론적으로 NetEase 서버와 Toutiao 서버에서 반환된 데이터는 동시에 동일한 노드여야 합니다. 이때 요청 데이터는 NetEase 및 Toutiao 서버로 동시에 전송되므로 이때 쿼리는 최대한 빨리 결과를 반환하기만 하면 됩니다. 좀 더 생생하게 표현하자면 데이터 군비 경쟁이라고 생각하면 됩니다. 물론 기존 지식을 활용하면 상대적으로 쉽게 완료할 수 있으므로 스레드 2개를 사용하고 콜백을 추가하면 되지만, 로직을 더욱 우아하게 만들기 위해 선택 기능을 사용하는 방법을 소개하겠습니다.
2. 사용방법
간단한 예를 들어 위의 논리에 따라 금 가격을 확인해 보겠습니다.
NetEase와 Toutiao에서 각각 골든 데이터 획득을 시뮬레이션하는 두 가지 시뮬레이션 함수를 정의합니다.
private suspend fun requestNestGoldData() = withContext(Dispatchers.IO){
Log.d("select","start to request nest gold data")
delay(100)
Log.d("select","get the nest gold data success")
"nest_" + 600.00
}
private suspend fun requestByteDanceData() = withContext(Dispatchers.IO) {
Log.d("select","start to request byte dance gold data")
delay(300)
Log.d("select","get the nest gold byte dance success")
"bytedance_" + 600.00
}
그런 다음 select 함수를 사용하여 데이터를 바인딩하고 가져옵니다.
viewModelScope.launch {
val requestDataResult = select {
async {
requestNestGoldData() }.onAwait {
it }
async {
requestByteDanceData() }.onAwait {
it }
}
Log.d("select","get the result : $requestDataResult")
}
그런 다음 인쇄 로그를 살펴보겠습니다.
2023-09-17 15:54:23.164 19063-19188 select D start to request nest gold data
2023-09-17 15:54:23.164 19063-19189 select D start to request byte dance gold data
2023-09-17 15:54:23.266 19063-19188 select D get the nest gold data success
2023-09-17 15:54:23.449 19063-19063 select D get the result : nest_600.0
2023-09-17 15:54:23.466 19063-19188 select D get the nest gold byte dance success
로그를 통해 우리 requestNestGoldData()
와 requestByteDanceData()
동시에 요청했지만 select
가장 빠른 결과만 반환된 것을 발견했습니다.물론 느린 인터페이스는 여전히 실행 중이지만 결과는 폐기됩니다.
3. 후속 조치
콜백을 사용한다면 어떻게 해야 할까요? 의사코드 구현을 작성해 보겠습니다.
interface ResultListener {
fun onResult(info String)
}
private suspend fun requestNestGoldDataWithListener(listner : Resultlistener) {
runBlocking(Dispatchers.IO){
Log.d("select","start to request nest gold data")
delay(100)
Log.d("select","get the nest gold data success")
listner.onResult("nest_" + 600.00)
}
}
private suspend fun requestByteDanceGoldDataWithListener(listner : Resultlistener) {
runBlocking(Dispatchers.IO){
Log.d("select","start to request byte dance gold data")
delay(100)
Log.d("select","get the nest byte dance data success")
listner.onResult("nest_" + 600.00)
}
}
viewModelScope.launch {
var hasResult : Boolean = false
val listener : ResultListener = object : ResultListener {
override fun onResult(info String){
if(!hasResult) {
hasResult = true
//deal with the result
}
}
}
requestNestGoldDataWithListener(listener)
requestByteDanceGoldDataWithListener(listener
}
의사코드가 나왔고, 그 과정은 여전히 매우 쉽다는 것을 알 수 있습니다. 이때 select
콜백을 사용하는 것과 Simple and Powerful을 사용하는 것의 차이를 보지 못할 수도 있습니다.