parent-child 관계에서 동시성
1. children은 parent로부터 context를 상속받는다
2. perent는 childern이 끝날 때까지 suspend된다.
3. parent가 취소되면 child의 모든 coroutine은 취소된다.
4. children의 destory되면 parent도 destory된다.
2,3,4는 Job
에 밀접한 관계를 가지고 있다.
job은 인터페이스이며, job을 통해 coroutine 취소
, 상태 추적
등을 할 수 있다.
각 job들을 생성해 active
, new
등의 상태를 출력해보자
suspend fun main() = coroutineScope {
val job = Job()
println(job)
job.complete()
println(job)
val activeJob = launch {
delay(1000)
}
println(activeJob)
activeJob.join()
println(activeJob)
val lazyJob = launch(start = CoroutineStart.LAZY) {
delay(1000)
}
println(lazyJob)
lazyJob.start()
println(lazyJob)
lazyJob.join()
println(lazyJob)
}
output
JobImpl{Active}@5b6f7412
JobImpl{Completed}@5b6f7412
StandaloneCoroutine{Active}@2b05039f
StandaloneCoroutine{Completed}@2b05039f
LazyStandaloneCoroutine{New}@13ae1124
LazyStandaloneCoroutine{Active}@13ae1124
LazyStandaloneCoroutine{Completed}@13ae1124
job들 역시 parent를 기반으로 job들을 생성한다.
job은 coroutine 없이 생성 가능하다. 이렇게 생성된 job들은 context처럼 쓰이곤 한다.
(많은 coroutine들의 parent 역활로 생각)
suspend fun main() = coroutineScope {
val job = Job()
launch(job) {
delay (1000)
println("Text1")
}
launch(job) {
delay(1000)
println("Text2")
}
//job.join() 다른 coroutine 들이 사용되기를 기다림
job.children.forEach { it.join() }
}
앞서 말했듯이 job은 interface라 생성자를 통해서 객체를 생성하지 못한다.
그러나 우리는 생성자를 사용하여 객체를 생성하는 것처럼 사용하고 있다.
public fun Job(parent: Job? = null) : CompletableJob
위의 코드와 같이 fake 생성자
를 통해서 생성자처럼 객체를 생성하고
반환하는 값 역시 Job이 아니라 CompletableJob 이다.