코루틴 Job
코틀린 코루틴 (7)
코루틴 Job
구조화된 동시성을 이야기할 때 코루틴 꽁 머니 카지노에 관한 언급이 있었다. 그렇다는 것은 꽁 머니 카지노가 가능하다는 말이다. 그럼 궁금점이 생긴다. 어떻게 하는 걸까?
제목이 코루틴 Job이니까 Job이라는 녀석을 사용해서 꽁 머니 카지노를 하나 보네? 그럼 코루틴 꽁 머니 카지노를 하는 방법은 Job을 이용하는 것이겠군!
위와 같이 생각했다면 후하게 매겨도 50점이다. 코루틴 꽁 머니 카지노에 관한 이야기가 주제가 아니라 Job이 주제인만큼 꽁 머니 카지노 그 자체에 포커스를 맞추면 안 된다. Job을 이용해서 꽁 머니 카지노를 할 수는 있다. 하지만 모든 코루틴에 관해서 그런 것은 아니다.
아 그래? 그럼 또 추측을 해볼까? 꽁 머니 카지노를 할 수 없는 코루틴도 존재하는구나!
이것도 50점이다. 꽁 머니 카지노 불가능하게 만들 수 있는 부분도 있다. 하지만 Job이 아닌 다른 객체를 통해서 꽁 머니 카지노해야 하는 코루틴도 있다. 다시 이전의 기억을 되짚어보자.코루틴 빌더를 기억하는가? 코루틴 빌더는 하나의 종류만 있는 것이 아니다. 그렇다면 이제 합리적인 추측을 해볼 수 있다.
Job을 사용하면 코루틴 빌더 중 한 녀석이 생성한 코루틴을 꽁 머니 카지노할 수 있겠구나. 아 그리고 꽁 머니 카지노에만 집중할 것이 아니니까 Job은 꽁 머니 카지노 외에도 뭔가 다른 임무를 수행할 것 같아!
이 정도가 정리되었다면 한결 이야기가 쉬워진다. 그래서 Job이 뭔데?
일단 놀랍게도 여기까지 오는 동안 Job을 몇 번이나 만들었다. Job은 코루틴 빌더인 launch를 통해 생성된다. 그러니까 launch를 작성했을 때마다 생성되었다는 것이다. launch의 구현부를 보라. 리턴 타입이 Job이다.
launch를 통해 코루틴을 생성했을 때마다 Job 객체가 반환되고 있었던 것이다. 단지 지금까지는 해당 객체를 받아와서 별도의 작업을 시도하지 않았을 뿐이다. 그럼 한번 해보자.
job이란 변수를 하나 만들어서 launch를 통해 생성된 Job 객체를 담았다. 그 후cancel()을 통해 launch에 의해 생성된 코루틴을 꽁 머니 카지노한다. 그렇다면 실행 결과는 어떻겠는가? Hello, 가 출력된 후 코루틴이 꽁 머니 카지노되어 World! 는 출력되지 못하고 끝난다.
이제구조화된 동시성에서언급했던부모 코루틴이 꽁 머니 카지노되면 자식 코루틴도 꽁 머니 카지노되는 경우도 간단하게 확인해 볼 수 있다.
부모 코루틴을 꽁 머니 카지노했을 때 자식 코루틴이 꽁 머니 카지노되지 않는다면 실행 결과는 Hello, Kotlin! 이 되어야 할 것이다.
코루틴이 정상적으로 꽁 머니 카지노되었다면 CancellationException이발생한다. 엥? 정상적으로 꽁 머니 카지노되었는데 왜 예외가 발생하지? 그 이유에도 이런저런 사유가 있지만 지금 굳이 그것까지 알아야 할까 싶다. 쉽게 생각하자면 꽁 머니 카지노를 했는데도 불구하고 꽁 머니 카지노되기 전까지 완료된 작업들이 예외적으로 완료가 된 것이라는 관점으로 보면 된다. 아무튼 예외가 발생한 것이다. 그래서 이 경우엔 정상적인 꽁 머니 카지노라고 본다. 대신에 다른 예외로 코루틴이 꽁 머니 카지노가 된다면 그건 정상적인 꽁 머니 카지노가 아니기 때문에 코루틴의 작업이 실패했다고 봐야 한다.
예외의 발생 여부는 다음과 같이 확인할 수 있다.
그런데 위의 예제 실행 결과가 조금 신경 쓰인다.
Hello,
Done!
Cancelled!
꽁 머니 카지노가 된 후에 완료하고 싶은데 Done! 이 먼저 출력되었다. 후후.. 이제 이 정도야 쉽지! println("Done!") 전에 delay(100L) 정도 선언해 주면 해결!
원하는 출력 형태는 얻을 수 있는 방법이다. 하지만 delay(10L)을 줘도 되는데 그럼 불필요하게 90ms 느리게 된 것이다. 즉 이 방법은 최선의 방법이 아니라는 것이다. 10ms만 기다려도 꽁 머니 카지노까지 모두 처리된다. 그럼 최선은 무엇인가? launch 내부가 완료될 때까지만 기다리면 된다.
그걸 어떻게?
앞에서 Job은 꽁 머니 카지노 외에도 뭔가 다른 임무를 수행할 것 같다고 추측했듯이 이것도 Job을 통해 할 수 있다. 바로 join()을 사용하면 된다.join()은 해당 코루틴이 완료될 때까지 기다리는 역할을 한다. 결과적으로
println("Done!") 전에 job.join()을 추가하면 다음과 같은 실행 결과를 얻을 수 있다.
Hello,
Cancelled!
Done!
여기까지 확인해 본 Job은 도대체 뭘 하는 녀석인가?
1. 코루틴을 꽁 머니 카지노할 수 있다.
2. 코루틴이 완료될 때까지 기다릴 수 있도록 한다.
이런 것들을 좀 더 추상화시킬 수 없을까? 꽁 머니 카지노, 완료 이런 것들을 좀 더 추상적인 표현으로 바꾸면 무엇으로 바꿀 수 있을까?상태라고 할 수 있다. 이렇게 상태를 제어하는 역할을 하는데 혹시 확인하는 역할을 못할까? 한다. Job.kt 내부에 주석으로 설명된 내용을 보면 다음과 같이 크게 여섯 가지 상태를 가진다. 그리고 세 가지 프로퍼티에 각 상태에 따른 특정한 값이 할당된다.
상태가 변하는 과정에 대한 도식화도 제공한다. (이건 깔끔하게 다시 그려보는 것이 좋겠다.)
위의 내용을 참고해서 여러 가지 코드를 작성해 보고 결과를 예측해 보면서 확인하는 과정을 거치면 많은 도움이 될 것이다. 예를 들면 아래 코드의 실행 결과를 예측해 보고 join()을 제거했을 때는 어떤 결과가 나올지 생각해 보는 식이다.
isCancelled가 true이고 isCompleted가 false인 경우는 Job이 꽁 머니 카지노되었지만 아직 완전히 종료되지 않은 경우이다. 이것은 Job이 꽁 머니 카지노 요청을 받았지만, 꽁 머니 카지노 처리가 완료되지 않았을 때 발생할 수 있다.
요약하자.
- Job은 launch를 통해 생성된다.
- Job은 코루틴을 꽁 머니 카지노할 수 있다.
- Job은 코루틴이 완료될 때까지 기다릴 수 있도록 한다.
- Job은 코루틴의 상태를 제어하고 추적한다.