Kotlin: Coroutine 기초

hjseo-dev·2022년 6월 3일
1

Android

목록 보기
14/18

📍 코루틴과 스레드

1. 특징

  • 메모리 구조의 차이
    프로세스 안에 메모리 할당받음 - 스레드 (스택할당)
    코루틴은 메모리를 할당을 받지 않고 힙(heap) 영역을 공유해서 사용 = 함수와 비슷함
  • 코루틴은 비선점형 멀티태스킹이다 : 동시에 돌아가도 실제로는 같은 시간에 수행되지 않는 것이다. 전환되며 속도가 빨라서 동시에 수행되는 것 처럼 보인다

2. 장점 (메모리, 오버헤드)

3개의 스레드를 코루틴으로 대체하면, 메모리를 할당하지 않아도 됨
분리된 영역을 처리할때 그 사이에서 데이터의 참조를 하는 것(context switching)을 하는 것이 아님 = 오버헤드가 생기지 않음

3. 사용법

suspend를 붙여서 쓴다 / 중간에 다른 작업이 가능!
(중간에 멈출 수 있는 함수라는 뜻)

📍 코루틴 구조

  • Coroutine Scope : 코루틴이 어떤 범위에서 동작할 지
  • Coroutine Context : 어떤 스레드에서 코루틴을 사용할 지
  • Coroutine Builder : 작업을 수행하여 값을 리턴할 지

💡 Coroutine Scope vs GlobalScope

  • 보통 스코프는 쓰고 버리고 가능 / global scope는 최상위 레벨에서 사용, 싱글톤이어서 만들어서 쓰고 버리고.. 하지 못함 (추천하지 않음)

💡 Coroutine Context의 구성

1. Dispatchers : 코루틴이 실행되는 스레드를 지정한다 (4가지 타입)

  • Default : CPU 연산을 많이 필요하는 작업에서 사용
  • IO : 파일, 네트워크 작업에서 사용
  • Main : UI 스레드(메인스레드) UI 관련 변경 시 사용
  • Uncomfined : 일반적으로 사용하지 않음

2. Job & Deffered
코루틴이라는 흐름을 job 이라는 오브젝트로 사용
= 오브젝트를 취소, 예외처리를 가능하게 하여 작업을 컨트롤 가능하게 해준다 (흐름제어 가능)

Job states cycle
                                         wait children
   +-----+ start  +--------+ complete   +-------------+  finish  +-----------+
   | New | -----> | Active | ---------> | Completing  | -------> | Completed |
   +-----+        +--------+            +-------------+          +-----------+
                    |  cancel / fail       |
                    |     +----------------+
                    |     |
                    V     V
                +------------+                           finish  +-----------+
                | Cancelling | --------------------------------> | Cancelled |
                +------------+                                   +-----------+

3. Coroutine Builder

  • launch : 코루틴 시작, Job 객체 반환
  • async : 코루틴 시작 가능 - Deffered 객체 반환
    -> async는 마지막에 숫자를 반환한다 / 메인 스레드에서 관계 없는 동작이 가능
  • runblocking : 사용 안함 / 메인 스레드에 영향을 준다
  • withContext : Dispatcher switch - 오버헤드가 적음
suspend fun fetchDocs() {                      // Dispatchers.Main
    val result = get("developer.android.com")  // Dispatchers.Main
    show(result)                               // Dispatchers.Main
}

suspend fun get(url: String) =                 // Dispatchers.Main
    withContext(Dispatchers.IO) {              // Dispatchers.IO (main-safety block)
        /* perform network IO here */          // Dispatchers.IO (main-safety block)
    }                                          // Dispatchers.Main
}

💡 코루틴 지연

  • delay : 정해진 시간 동안 코루틴 처리 불가 (대기상태)
  • join : launch로 실행한 코루틴은 join으로 대기 가능
  • await : async로 실행한 코루틴은 await로 대기 가능 / deffered 값을 반환하게 된다

💡 코루틴 취소

  • cancel : job을 Cancelling (transient state)로 변화
  • cancelAndJoin : job을 캔슬하고 Cancelled가 될때 까지 기다림
  • withTimeout : 제한시간을 설정하고 그때까지 처리가 끝나지 않았을 경우 블럭을 취소하고 TimeoutCancellationException을 throw
  • withTimeoutOrNull : 제한 시간 안에 처리 못할 경우 null 반환

💡 코루틴 사용

스코프는 CoroutineScope를 사용합니다. CPU 작업이냐 IO 작업이냐를 판단하여 Dispatchers를 정의하고 마지막으로 코루틴 처리후 값이 나와야 되는가 아닌가에 따라 launch나 async를 구별해서 사용하면 되겠습니다.

참조 : 냉동코더의 기술블로그

0개의 댓글