우찬쓰 개발블로그
코틀린 코루틴의 정석 본문
저자 조세영
코루틴 관련 문서나 책은 많이 읽었지만, 이렇게 깔끔하게 정리된 책은 처음보는것 같다.
덕분에 머리에서 정리가 잘 안되어 있거나 헷갈리던 부분을 다시 되짚어 볼 수 있었다.
아래는 자주 잊어버리는 부분만 정리.
코루틴은 스레드 블로킹을 해결하기 위해 등장했다. 스레드를 양보할 수 있다.
<CoroutineDispatcher>
- 코루틴을 쓰레드로 보내기 위한 역할
Dispatchers.IO
- 쓰레드 수 = JVM 프로세서수 or 64 중 큰 수
Dispatchers.Default
- 쓰레드 수 = CPU 코어수
- CPU연산(CPU 바운드 작업)에 주로 사용.
<Coroutine Context 요소>
- CoroutineName
- CoroutineDispatcher
- Job
- CoroutineExceptionHandler
코틀린 취소는 자식으로 전파됨
예외 throw는 해당 코루틴에서 이미 처리된 것으로 보므로 그 부모이상에 exception handler를 넣어야함
예외를 더 위로(부모로) 전파하지 않기 위해
SupervisorJob
SubervisorScope
fun main() = runBlocking {
val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
println("[예외 발생] ${throwable}")
}
val supervisedScope = CoroutineScope(SupervisorJob() + exceptionHandler)
supervisedScope.apply {
launch(CoroutineName("test1")) {
throw Exception("exception")
}
launch(CoroutineName("test2")) {
delay(100)
println("${Thread.currentThread().name}}")
}
}
delay(1000L)
}
<코루틴 실행 순서>
fun main() = runBlocking {
launch {
println("task1")
}
println("task2")
}
// task2
// task1
// runBlocking 코루틴에서 양보하는 부분이 있어야 그 다음에 task1이 실행
fun main() = runBlocking {
launch(start = CoroutineStart.UNDISPATCHED) {
println("task1")
}
println("task2")
}
// task1
// task2
// Dispatcher 객체의 작업 대기열을 거치지 않고 곧바로 호출자의 스레드에 할당돼 실행
withContext
- 새로 코루틴 생성하는것 아님
- Coroutine Context를 변경 가능
mutex를 통해 다중 스레드 동시 접근을 막을 수 있음
var count = 0
val mutex = Mutex()
fun main() = runBlocking {
withContext(Dispatchers.Default) {
repeat(10000) {
launch {
mutex.withLock {
count += 1
mutex.unlock()
}
}
}
}
println("count = $count")
}
advanceTimeBy 와 advanceUntilIdle
- advanceTimeBy는 특정 시간만큼 가상 시간이 흐르도록 하는 것
- advanceUntilIdle 는 TestCoroutineScheduler 에 연결된 모든 디스페처와 연결된 작업이 모두 완료될 때까지 가상 시간을 흐르게 만듦
'개발서 정복' 카테고리의 다른 글
불안한 완벽주의자를 위한 책 (0) | 2024.01.22 |
---|---|
리팩터링 2판 (0) | 2023.11.14 |
Jetpack Compose Internals (0) | 2023.07.23 |
이펙티브 코틀린 (0) | 2023.03.16 |
클린코더 (0) | 2023.01.26 |