Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

훌륭한 개발자가 되기 위하여

코루틴 제어 본문

안드로이드

코루틴 제어

jay20033 2025. 1. 7. 13:38

코루틴 순차 처리

토큰을 받아서 업데이트 한 후 네트워크 요청을 해야한다고 가정했을 때, 업데이트 되기 전에 네트워크 요청이 되면 권한 없음과 같은 오류가 발생할 수 있다.

 

만약 A 코루틴이 완료된 후에 B 코루틴이 실행되야 한다면, B 코루틴이 실행되기 전에 A 코루틴에 대해 join 함수를 호출하면 된다.

이 때, Job 객체의 join 함수를 사용하면 코루틴 순차 처리가 가능하다.

 

fun main() = runBlocking<Unit> {
    val job1 = launch(Dispatchers.IO) {
        println("작업 1")
        delay(1000L)
        println("작업 2")
    }
    job1.join()
    val networkCallJob = launch(Dispatchers.IO) {
        println("네트워크 요청")
    }
}

 

Join 함수를 사용하면 join 함수의 대상이 된 코루틴이 완료될 때까지 join 함수를 호출한 코루틴이 일시 중단된다.

👉 runBlocking 코루틴이 job1이 완료될 때까지 일시 중단된다.

 

joinAll() : 인자로 받은 job이 모두 완료될 때까지 대기

joinAll(job1, networkCallJob)

 

joinAll 내부 코드는 아래와 같다.

public suspend fun joinAll(vararg jobs: Job): Unit = jobs.forEach { it.join() }

 

jobList도 가능하다. 👉 listOf(job1, networkCallJob).joinAll()


지연 코루틴

👉  즉시 실행 요청되지 않는 코루틴

launch 함수의 start인자로 CoroutineStart.LAZY를 넘기면 된다.

fun main() = runBlocking<Unit> {
	val lazyJob = launch(start = CoroutineStart.LAZY) {
			...
		}
	}

이대로 실행하면 출력이 되지 않음

👉  지연 코루틴은 start 함수나 join함수로 호출하면 실행된다.

lazyJob.start() or lazyJob.join()


코루틴 취소

코루틴 실행 도중, 실행할 필요가 없는 경우 즉시 취소해야 한다.

👉  취소하지 않으면 코루틴이 스레드를 계속 사용해서 성능 저하가 발생한다.

job.cancel()

cancel 함수는 코루틴을 곧바로 취소하지 않고, 취소 확인용 플래그를 ‘취소 요청됨’으로 바꾸는 역할만 한다.

👉  취소가 언제되는지 확실하지 않기 때문에 cancel 함수를 사용하는 것은 순차성 관점에서 중요한 문제를 가진다.

해결방법

cancelAndJoin() : 취소 요청한 후 취소가 완료될 때까지 호출 코루틴을 일시 중단

👉 delay로 취소 확인 시점을 만드는 것 대신 Thread.sleep을 사용하면 Thread가 중단되므로 효과 없음


코루틴 취소 확인 시점

  1. 일시 중단 시점
  2. 코루틴이 실행을 대기하는 시점

취소 확인 시점 만들기

  1. delay 함수
    1. 특정 시간만큼 코루틴을 일시 중단하게 만든다.
      1. 일시 중단 시점에 코루틴의 취소가 확인돼 취소된다.
      2. 불필요하게 작업을 지연시켜 성능 저하가 발생한다.
  2. yield 함수
    1. yield 함수를 호출한 코루틴은 자신이 사용하던 스레드를 양보한다.

               👉 스레드를 양보한 후 곧바로 재개 요청되기 때문에 delay  함수보다 효율적

               👉 재개 시에는 CoroutineDispatcher에 의해 다시 스레드로 보내지는 과정을 거치기 때문에 비효율적이다.

 

  3. CoroutineScope.isActive

       코루틴에 취소가 요청되었는지 확인할 수 있다.

      👉 코루틴에 취소가 요청되면 isActive가 false 된다.


코루틴의 상태

  • 생성(New)
  • 실행중(Active)
  • 실행 완료중(Completing)
    • 부모 코루틴의 모든 코드가 실행됬지만, 자식 코루틴이 실행 중인 경우 부모 코루틴이 갖는 상태
    • 부모 코루틴이 더 이상 실행할 코드가 없더라도 자식 코루틴이 모두 완료될 때까지 기다리는데 이때 실행 완료 중 상태에 머무른다.
    • 자식 코루틴이 모두 완료되면 부모 코루틴은 자동으로 실행 완료 상태로 전환된다.
  • 실행 완료(Completed)
  • 취소 중(Cancelling)
  • 취소 완료(Cancelled)

job 객체를 출력하면 코루틴의 상태가 나온다.


Job 객체의 상태 변수

  • isActive : 코루틴이 활성화 되어 있는지 여부. ‘실행 중’ 상태일 때 true 반환
  • isCancelled : 코루틴에 취소가 요청됬는지 여부. cancel 함수가 요청되기만 하면 true를 반환하므로 취소 중인 상태도 포함
  • isCompleted : 코루틴이 완료되었는지 여부. 코루틴이 완료되거나 취소 완료되면 true 반환

👉 취소 중일 때는 코루틴은 계속 실행되지만 isActive는 false가 출력됨

코루틴 상태 isActive isCancelled isCompleted
생성 false false false
실행 중 true false false
실행 완료 중 true false false
실행 완료 false false true
취소 중 false true false
취소 완료 false true true
  1.