개발
coroutine - launch, async, CoroutineContext
kwony
2023. 2. 28. 20:00
launch, async
coroutine을 시작하는 방법은 launch, async가 있다. launch는 결과값을 반환하지 않고 async는 await를 이용해서 결과값을 반환할 수 있다.
fun main() {
ThreadTest().runCoroutine()
}
class ThreadTest {
fun runCoroutine() = runBlocking {
val jobs = ArrayList<Deferred<Int>>()
(1..5).map { number ->
val job = async {
delay((Math.random() * 1000).toLong())
println("${Thread.currentThread().name} done, number: $number")
increaseCounter()
return@async number
}
jobs.add(job)
}
jobs.forEach {
println("result: ${it.await()}")
}
}
}
-------------------------------------------------------------------------
main done, number: 3
main done, number: 1
result: 1
main done, number: 5
main done, number: 2
result: 2
result: 3
main done, number: 4
result: 4
result: 5
코드에서 async 를 사용한 코루틴은 number 값을 리턴하도록 했고 jobs 리스트에서 그 값을 출력하도록 했다. 그 결과 1 부터 5까지 출력되는 것을 확인 할 수 있다.
fun main() {
ThreadTest().runCoroutine()
}
class ThreadTest {
fun runCoroutine() = runBlocking {
val jobs = ArrayList<Job>()
(1..5).map { number ->
val job = launch {
delay((Math.random() * 1000).toLong())
println("${Thread.currentThread().name} done, number: $number")
increaseCounter()
}
jobs.add(job)
}
jobs.forEach {
it.start()
}
}
}
-------------------------------------------------------------------------
main done, number: 4
main done, number: 3
main done, number: 1
main done, number: 2
main done, number: 5
이번에는 async 대신 launch를 사용했다. launch로 코루틴을 선언하면 리턴값으로 Job을 받는다. jobs 변수에서 job 별로 start() 함수를 호출해 실행하도록 했더니 결과가 병렬적으로 처리되는 것을 확인 할 수 있었다.
CoroutineContext
그런데 출력 결과에서 신기한 점이 있다. 작업을 처리하는 쓰레드 이름이 모두 main으로 출력된 것이다. 코루틴을 실행할 때 CoroutineContext 를 정해주면 코루틴을 실행할 쓰레드를 지정할 수 있다. 코루틴 디스패쳐는 코루틴 작업을 특정 쓰레드 풀에 위임하고 실행한다. 작업에 따라서 쓰레드를 다르게 가져갈 수 있다.
fun main() {
ThreadTest().runCoroutine2()
}
class ThreadTest {
fun runCoroutine2() = runBlocking {
launch {
println("thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) {
println("thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) {
println("thread ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyOwnThread")) {
println("thread ${Thread.currentThread().name}")
}
}
}
-------------------------------------------------------------------------
thread main
thread DefaultDispatcher-worker-1
thread main
thread MyOwnThread
launch에 CoroutineContext 옵션을 넣어서 코루틴을 실행하는 쓰레드를 변경할 수 있다. 그 결과 출력된 쓰레드 이름이 다른것을 확인할 수 있다.