코루틴은 일시 중단이 가능한 작업 객체로 동시성을 지원하는 관점에선 스레드와 유사한점이 많다.
하지만 코루틴은 분명 스레드에서 동작하지만 그 어떤 스레드에 종속되진 않는다.
하나의 코루틴 작업을 스레드 이곳저곳을 돌아다니며 실행시킬 수 있기 때문이다.
이러한 코루틴을 만드는 방법은 CoroutineBuilder를 활용하는 것이다.
CoroutineBuilder는 말그대로 코루틴을 만드는 코루틴 객체 생성자이다.
CoroutineBuilder는 launch, async 이렇게 두 개로 볼 수 있다.
launch, async를 알아보기에 앞서 Dispatchers에 대해 잠깐 알고 넘어가자.
Dispatchers는 코루틴의 실행을 관리해주는 CoroutineContext로 스레드에 코루틴의 실행을 분배하거나 특정 스레드 풀로 전달하는 역할을 한다.
즉, 코루틴을 만든 다음 Dispatcher를 사용하여 코루틴의 작업이 동작할 스레드를 지정할 수 있다.
안드로이드의 경우 이미 기본으로 Dispatcher가 생성되어 있기 때문에 별도로 정의는 필요 없다.
안드로이드가 기본으로 제공하는 Dispatcher는 다음과 같다.
- Dispatchers.Main - 메인 스레드에서 코루틴을 실행하는 Dispatcher로 UI와 상호작용하는 작업을 실행하기 위해 사용해야 한다.
- Dispatchers.IO - 디스크 또는 네트워크 I/O 작업을 실행하는데 최적화된 Dispatcher이다.
- Disaptchers.Default - CPU가 많이 사용되는 작업을 기본 스레드 외부에서 실행하도록 최적화된 Dispatcher이다.
그럼 이제 launch와 async에 대해 알아보자!
launch
코루틴 동작을 실행하거나, 동작여부, 코루틴 블럭의 동작이 완료될 때 까지 대기할 필요가 있을경우 launch를 사용한다.
launch를 사용할 경우 별도의 결과는 없고 job 객체가 반환된다.
launch로 만들어진 job 객체는 join() 메소드를 통해 해당 스코프 내의 코루틴 동작을 모두 수행할때까지 대기하도록 할 수 있다.
fun main() = runBlocking{
launch {
delay(1000L)
println("coroutine launch1")
}
launch {
delay(2000L)
println("coroutine launch2")
}
println("done")
}
//done
//coroutine launch1
//coroutine launch2
async
기본적으로 launch와 비슷하게 코루틴을 생성하고 용법도 비슷하다. 다만, 코루틴 동작을 모두 수행 한 뒤 반드시 최종적으로 수행 결과를 반환해야 한다.
값이 반환될 때까지 코루틴의 흐름을 정지시키고 싶다면 Defferd의 await()를 호출하면 되는데 이 메소드가 호출되면 코루틴은 결과를 반환할 때까지 기다리게 된다. 즉 await() 메소드를 통해 동시성을 보장받을 수 있다.
val async1: Deferred<Int> = async{
delay(1000L)
10
}
val async2: Deferred<Int> = async{
delay(1000L)
20
}
fun main() = runBlocking {
val time = measureTimeMillis {
println("result : ${async1.await() + async2.await()}")
}
println("total elapsed time : $time ms")
}
//result : 20
//total elapsed time : 1021 ms
'Kotlin' 카테고리의 다른 글
[Kotlin] runCatching (0) | 2022.12.19 |
---|---|
[Kotlin] 스레드와 코루틴 (0) | 2022.05.12 |
[Kotlin] Object (0) | 2022.03.25 |
[Kotlin] Delegated Properties (0) | 2022.03.23 |
[Kotlin] Delegation (0) | 2022.03.22 |