본문 바로가기

코틀린/개념

[kotlin/코틀린] 코루틴 (Coroutine)

목차

1. CoroutineScope

2. CoroutineContext

3. Dispatcher

4. lauch, async, job, deferred

5. runBlocking

 

1. CoroutineScope

1-1) CoroutineScope란?

코루틴의 범위, 코루틴 블록( 하나 또는 그 이상 )을 제어할 수 있는 단위

 

1-2) 범위

        val job = CoroutineScope(Dispatchers.Main).launch {
            CoroutineScope(Dispatchers.Default).launch {}
        }
        job.cancel()

코루틴 내부에 또 다른 코루틴을 만들게 되면 외부와 내부의 코루틴 각각의 제어 범위는 다르다.

즉, 외부 코루틴의 job을 받아 cancel()을 하더라도 내부 코루틴을 제어할 순 없다.

각각의 코루틴은 제어 범위가 독립적이다.

 

 

2. CoroutineContext

2-1) CoroutineContext란?

Job과 Dispatcher를 주요 요소로 가지고, 코루틴을 어떻게 처리할 것인지에 대한 집합이다.

 

 

3. Dispatcher

3-1) Dispatcher란?

CoroutineContext를 상속 받아 어떤 쓰레드를 사용하여 어떻게 동작할 것인지에 대한 정의가 되어있다.

 

3-2) 종류

-Dispatchers.Default

CPU 사용량이 많은 작업에 적합, 주 스레드에서 작업하기에 긴 작업들에게 알맞다. 

-Dispatchers.IO

네트워크 또는 디스크를 사용할 때 적합하다. 파일을 읽고, 쓰고, 소켓을 읽고, 쓰는 작업을 멈추는 것에 최적화되어 있다.

-Dispatchers.Main

메인 스레드를 기본으로 동작, 포그라운드 작업 , 안드로이드의 경우 UI 작업에 적합하다.

 

3-3)예제

       val scope = CoroutineScope(Dispatchers.Main)
        //포그라운드
        scope.launch {}
        //백그라운드
        scope.launch(Dispatchers.Default){}
        scope.launch(Dispatchers.IO) {}
        //CoroutineContext를 변경하더라도 기존의 scope는 유지된다.

 

 

4. lauch, async, job, deferred

4-1) lauch, async란?

CoroutineScope의 확장함수이다. 코드 블록으로 코루틴을 만들고 실행해주는 코루틴 빌더이다.

 

4-2) job, deferred란?

job : launch()로 시작된 코루틴 블록은 Job 객체를 반환한다. 

deferred : async()로 시작된 코루틴 블록은 Deferred 객체를 반환한다. 

job과 deferred 모두 코루틴 블록을 제어할 수 있다. 차이점은 job 결과값 반환 X deferred는 결과값 반환 O

 

4-3) job, deferred 예제

        CoroutineScope(Dispatchers.Main).launch {
            //job
            val job = launch {
                var i = 0
                while (i<100){
                    delay(500)
                    i++
                }
            }
            val job2 = launch {
                var i = 0
                while (i<100){
                    delay(500)
                    i++
                }
            }
            //완료까지 대기
            //방법 1)
            job.join()
            job2.join()

            //방법 2)
            joinAll(job,job2)

            //방법 3)
            val job3 = launch {}
            launch(job3) {}
            job3

            //취소
            job.cancel()
        }
        CoroutineScope(Dispatchers.Main).launch {

            val deferred = async {}
            val deferred2 = async {}

            //완료 대기
            //방법 1)
            deferred.await()
            deferred2.await()

            //방법 2)
            awaitAll(deferred,deferred2)

            //방법 3)
            val deferred3 = async {}
            async(deferred3) {}
            deferred3.await()

            //결과값 반환
            //방법 1)
            val deferred4 : Deferred<String> = async { "OK" }
            val result = deferred4.await()

            //방법 2)
            val deferred5 = async { "OK2" }
            val result2 = deferred5.await()

        }

 

4-4) 지연 실행

CoroutineStart.LAZY 인자값을 사용하여 코루틴 블록의 실행을 지연시킬 수 있다.

        CoroutineScope(Dispatchers.Main).launch {

            val job = launch(start = CoroutineStart.LAZY) {}
            job.start()
            //or
            job.join()

            val deferred = async(start = CoroutineStart.LAZY) {}
            deferred.start()
            //or
            deferred.await()
        }

*주의

deferred.start() 시에는 완료까지 기다리지도 않고 수행 결과를 반환하지 않는다.

 

 

5. runBlocking

5-1) runBlocking란?

lauch()와 async()는 각각 join(), await()로 블록의 작업 완료를 기다린다.

그러나 runBlocking()는 추가적인 함수 호출 없이 해당 블록이 끝날 때까지 기다리는 것이다.

'코틀린 > 개념' 카테고리의 다른 글

[kotlin/코틀린] 상속  (0) 2021.07.04