일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- viewmodel
- 스레드 vs 코루틴
- runCatching
- 코틀린 에러 핸들링
- BOJ
- power menu
- hilt
- 코루틴 공식문서
- AAC ViewModel
- Sticky Header RecyclerView
- 코루틴 공식 문서
- 안드로이드 커스텀 뷰
- Kotlin Serialization
- android compose orbit
- 백준
- 백준 2615
- Android Custom View
- power menu 라이브러리
- 힐트
- android orbit
- Android Compose
- Hilt 에러
- 안드로이드 무한 스크롤
- RecyclerView Sticky Header
- Android Compose Navigation
- Coroutine
- 안드로이드 컴포즈
- Unsupported metadata version. Check that your Kotlin version is >= 1.0: java.lang.IllegalStateException
- Thread vs Coroutine
- 코루틴
- Today
- Total
Beeeam
코루틴 공식 문서 읽기 (Coroutines basics) 본문
안드로이드 면접 스터디를 진행하면서 코루틴에 대해서 공부하게 되었는데 이를 정리해보려고 한다. 참고로 코루틴 공식 문서를 참고하여 공부하였다.
https://kotlinlang.org/docs/coroutines-basics.html
Coroutines basics | Kotlin
kotlinlang.org
코루틴?
코루틴은 비동기적으로 실행되는 코드를 간소화 하기 위해 사용되는 설계 패턴이다.
스레드와 개념적으로는 비슷하지만 코루틴은 특정 스레드에 포함되지 않는다. 그리고 코루틴은 스레드보다 더 가벼울 수 있다.
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello") // main coroutine continues while a previous one is delayed
}
위의 코드를 실행하게 되면 다음과 같은 결과가 나온다.
Hello
World
launch: 코루틴 빌더로 새로운 코루틴을 생성하고, 나머지 코드와 동시에 실행한다. 근데 보통 나머지 코드가 먼저 실행된다.
delay: delay는 일시정지를 하는 함수이다. delay에 인자로 특정 시간을 전달 해주면 전달된 특정 시간 만큼 코루틴이 정지하게 된다.
runBlocking: 얘도 코루틴 빌더이고, 코루틴 범위를 설정한다. 얘를 빼고 작성하면 오류가 발생한다.
Structured concurrency
코루틴은 구조화된 동시성의 원칙을 따른다. 구조화된 동시성은 새로운 코루틴은 코루틴의 수명을 구분하는 특정 코루틴 스코프에서만 실행이 될 수 있다는 것을 의미한다.
Extract function refactoring
fun main() = runBlocking { // this: CoroutineScope
launch { doWorld() }
println("Hello")
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
launch 블럭 안에 doWorld 라는 함수가 있는데 이는 suspend 라는 식별자를 갖고 있다. suspend가 뭘까? suspend 함수는 코루틴 안에서는 일반적인 함수로 사용될 수 있는 함수로, 이 suspend 함수는 일반 함수과 달리 delay와 같은 다른 중단 함수들을 호출 할 수 있다.
이러한 이유는 suspend 함수 역시 중단 함수이기 때문에 특정 코루틴 컨텍스트 안에서 실행 되고 있고, 코루틴 컨텍스트 안에서는 모든 중단 함수를 호출 할 수 있기 때문이다.
Scope builder
CoroutineScope{ } 빌더를 사용하면 코루틴의 사용자가 지정한 범위를 선언하고, 생성할 수 있다. 이렇게 생성된 코루틴은 모든 자식 코루틴들이 끝날 때 까지 완료 되지 않는다.
runBlocking, coroutineScope 빌더들은 비슷해 보일 수 있다. 둘 다 본문과 모든 자식들이 완료 될 때 까지 기다리기 때문이다. 하지만 다르다.
runBlocking과 달리 coroutineScope는 자식들의 종료를 기다리는 동안 현재 스레드를 블록 하지 않는다.
Scope builder and concurrency
fun main() = runBlocking {
doWorld()
println("Done")
}
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
launch {
delay(2000L)
println("World 2")
}
launch {
delay(1000L)
println("World 1")
}
println("Hello")
}
위의 코드를 실행하면 결과는 다음과 같이 나온다.
Hello
World 1
World 2
Done
doWorld 함수를 실행하게 되면, doWorld 함수 안에 첫 번째 launch를 실행하게 된다. delay가 걸려 있기 때문에 실행을 하면서 다음 launch로 이동한다. 두 번째 launch 안에도 delay가 있기 때문에 다음으로 이동한다. 그러면 마지막에 있는 “Hello”를 먼저 출력하게 되고, 다음에 delay가 더 짧은 두 번째 launch의 결과인 “World 1”이 출력이 된다. 그리고 첫 번째 launch의 결과인 “World 2”가 출력이 된 후에 doWorld를 빠져나와 “Done”이 출력이 된다.
An explicit job(명시적 작업)
launch 코루틴 빌더는 실행된 코루틴에 handle인 Job 객체를 반환하고, Job 객체는 코루틴 실행이 완료될 때까지 명시적으로 대기하는 데 사용할 수 있다.
val job = launch { // launch a new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello")
job.join() // wait until child coroutine completes
println("Done")
위의 코드를 실행하면 다음과 같은 결과가 출력된다.
Hello
World
Done
“Hello”와 “Done”이 출력 되는 명령 사이에 job.join() 때문에 자식 코루틴이 끝날 때 까지 기다리게 된다. 그래서 “Hello” → “World” → “Done” 순서로 출력이 된다.
Coroutines are light-weight
코루틴은 JVM 스레드에 비해 리소스가 집약적이지 않다. 스레드를 사용할 때 JVM의 가용 메모리를 소진하는 코드는 코루틴을 사용하면 리소스 제한에 도달하지 않고 표현이 가능하다.
'Kotlin' 카테고리의 다른 글
코루틴 공식 문서 읽기 (Asynchronous Flow 2) (1) | 2023.04.13 |
---|---|
코루틴 공식 문서 읽기 (Asynchronous Flow 1) (0) | 2023.04.13 |
코루틴 공식 문서 읽기 (Coroutine context and dispatchers) (0) | 2023.03.28 |
코루틴 공식 문서 읽기 (Composing suspending functions) (0) | 2023.03.13 |
코루틴 공식 문서 읽기 (Coroutine Cancellation and timeouts) (0) | 2023.03.05 |