3장.라이프 사이클과 에러 핸들링
Job과 Deferred
- 결과가 없는 비동기 함수: Job vs 결과가 있는 비동기 함수: Deferred
Job
- 파이어 앤 포겟(fire-and-forget) 작업
- 특정 상태에 도달하면 이전 상태로 되돌아가지 않는다.
- 코루틴 빌더 launch{} 를 이용
- 예외는 Job을 생성한 곳까지 전파시킨다.
//job은 예외를 던진 곳까지 전파시킨다.
fun main(args : Array<String>) = runBlocking{
val job = GlobalScope.launch {
TODO("Not Implemented")
}
delay(2000L)
}
생명주기
생성(New)
- 존재하지만 아직 실행되지 않은 Job
- CoroutineStart.LAZY를 통해 Job을 자동으로 시작시키지 않을 수 있다.
fun main(args : Array<String>) = runBlocking{
val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
TODO("Not Implemented")
}
delay(2000L)
}
활성(Active)
- 실행중인 Job, 일시 중단된 Job도 포함
- join() vs start()
- join(): Job의 완료를 기다림
- start(): Job의 완료를 기다리지 않음
fun main(args : Array<String>) : Unit = runBlocking{
val job = GlobalScope.launch(start = CoroutineStart.LAZY) {
delay(2000L)
println("Complete")
}
job.join()
}
join()는 Job의 완료를 기다리기 때문에 일시 중단 함수 or 코루틴에서 호출해야 한다.
fun main(args : Array<String>) {
val task = GlobalScope.launch {
delay(1000L)
println("Complete")
}
task.start()
}
Complete 출력 없이 프로그램이 종료되는 것을 확인할 수 있다.
취소 중(Canceling)
- 활성과 취소의 중간 단계
- 실행 중인 Job에서 cancel() 호출하여 취소가 완료 될 때 까지
취소 됨(Cancelled)
- 취소로 완료된 Job
- 취소와 완료는 같은 상태이므로 CoroutineException Handler를 이용하여 판단
//handler 처리
fun main(args : Array<String>) = runBlocking{
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
println("Job cancelled due to ${throwable.message}")
}
GlobalScope.launch(exceptionHandler) {
TODO("Not implemented yet")
}
delay(2000L)
}
//invokeOnCompleteion 처리
fun main(args : Array<String>) = runBlocking{
GlobalScope.launch {
TODO("Not implemented yet")
}.invokeOnCompletion { cause ->
cause?.run {
println("Job Cancelled due to $this")
}
}
delay(2000L)
}
완료 됨(Completed)
- Job이 더 이상 실행 x, 취소된 Job도 포함
Deferred
- 결과를 갖는 비동기 작업에 수행하기 위한 목적
- 객체를 반환, 객체는 비동기 작업이 완료될 때까지 비어있다.
- 처리되지 않은 예외를 자동으로 전파하지 않는다.
- join()은 에러를 전파하지 않고 처리하는 반면 await()는 단지 호출하는 것만으로 예외가 전파된다.
//try-catch 문으로 예외 처리가 가능하다.
fun main(args : Array<String>) : Unit = runBlocking{
val deferred = GlobalScope.async {
TODO("Not implemented yet")
}
try {
deferred.await()
}catch (e : Throwable){
println("Deferred cancelled due to ${e.message}")
}
}
- Job과 동일한 방법으로 CoroutineExceptionHandler로 처리할 경우, MainThread에 에러가 전파되어 MainThread가 에러로 인해 종료된다.
따라서, CoroutineExceptionHandler를 이용하기 위해선 에러를 전파받는 위치에 Handler를 추가하는 것이다.
//에러를 전파 받는 곳에 handler를 이용한다.
fun main(args: Array<String>): Unit = runBlocking {
val exceptionHandler = CoroutineExceptionHandler{_, handler ->
println("Defered cancelled due to ${handler.message}")
}
val deferred = GlobalScope.async {
TODO("Not implemented yet")
}
GlobalScope.launch(exceptionHandler){
deferred.await()
}.join()
}
상태는 한 방향으로 이동
- Job이 특정 상태에 도달하면 이전 상태로 되돌아가지 않는다.
fun main(args: Array<String>): Unit = runBlocking {
val task = measureTimeMillis {
val job = GlobalScope.launch{
delay(2000L)
}
job.join()
//restart
job.start()
job.join()
}
println("Time: $task ms")
}
2초 정도의 시간이 출력되는 것을 확인할 수 있다
참고
- learning Concurrency in Kotlin
- Coroutine 10. Deferred를 이용한 결과값 수신
Author And Source
이 문제에 관하여(3장.라이프 사이클과 에러 핸들링), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jms8732/3장-라이프-사이클과-에러-핸들링저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)