ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • coroutine - launch, async, CoroutineContext
    개발 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 옵션을 넣어서 코루틴을 실행하는 쓰레드를 변경할 수 있다. 그 결과 출력된 쓰레드 이름이 다른것을 확인할 수 있다.

    댓글

Designed by Tistory.