코루틴 컨텍스트
CoroutineContext 에는 Main, IO, Default의 세 가지가 있다.
- Main은 말 그대로 메인 쓰레드에 대한 Context이며 UI 갱신이나 Toast 등의 View 작업에 사용된다.
- IO는 네트워킹이나 내부 DB 접근 등 백그라운드에서 필요한 작업을 수행할 때 사용된다.
- Default는 크기가 큰 리스트를 다루거나 필터링을 수행하는 등 무거운 연산이 필요한 작업에 사용된다.
코루틴 빌더
launch
- 새로운 코루틴을 만들어주는 빌더 역할을 한다.
- 이녀석을 사용하려면 코루틴 스코프가 필요하다.
- UI 작업 O
- Job을 반환한다
runBlocking
- 얘도 코루틴 빌더역할을 한다.
- 자식 스레드가 완료될 때 까지 현재 대기중인 스레드를 block한다.
- 정규함수다
코루틴 Scope
CoroutinScope
- (자식 스레드가 완료될 때 까지 현재 스레드를 block 하지 않는다.)
- 일시중단 함수다.
- 여러 동시 작업을 수행할 수 있다
GlobalScope
- ( 전역으로 사용되는 스코프, 실행하는동안 일부 메모리 자원을 계속 소비 )
- 메인쓰레드가 종료되면 종료된다. (Like 데몬스레드 )
( 데몬 스레드는 일반 스레드가 모두 종료되면 더는 할 일이 없으므로, 데몬 스레드 역시 자동으로 종료됩니다.)
"launch는 그냥 스레드를 돌려두는 것이고, coroutineScope 자체가 async/await 할때까지 기다린다"
코루틴 Suspend function
suspend
delay
- suspend 로 일시정지 한다 ( Thread.sleep은 쓰레드 블로킹을 한다는 점에서 차이가 있다 )
- 코루틴 스코프내, 다른 suspend 내에서 만 사용가능
join()
- 다른 코루틴이 작동하는 동안 delay하는 것은 좋지 않은 접근 방법입니다.
- 백그라운드 작업이 완료될때까지 join()을 사용하여 명시적으로 기다려야합니다.
코루틴의 코드가 멈추는 경우 ( 예를 들어 너무 오랜 시간동안 delay되는 경우 ),
너무 많은 코루틴을 실행하여 메모리가 부족하면 어떻게 될까요?
즉, 실행된 모든 코루틴에 대한 참조를 수동으로 유지하고 이들을 join() 해야 하는 것은 오류가 발생하기 쉽습니다.
해결방법은 GlobalScope에서 coroutines (TOP 레벨 코루틴 )를 시작하는 대신
일반적으로 Thread( thread는 항상 전역 )와 마찬가지로, 수행중인 작업의 특정 범위에서 동시 루틴을 시작할 수 있습니다.
=> Top 레벨 코루틴을 만들지말고, 차일드 코루틴으로 하자 ( 부모코루틴이 기다려주기 때문에 )
runBlocking를 포함한 모든 코루틴 빌더는 CoroutineScope 인스턴스를 추가합니다.
외부 코루틴에서는 범위 내에서 시작된 모든 코루틴이 완료 될 때까지 코루틴을 완료하지 않기 때문에
명시적으로 처리하지 않고도 ( join() ) 이 범위에서 코루틴을 시작할 수 있습니다.
=> Structured Concurrency (구조화된 동시성)
fun test4_1() = runBlocking {
var job : Job = GlobalScope.launch {
delay(1000L)
Log.d("Woongs", "GlobalScope")
}
Log.d("Woongs", "main")
job.join()
// job이 완료될때까지 기다린다.
// job이 많아지만... 다 join() 해줘야 하네.?
}
// 개선
// GlobalScope를 사용하지 않고 runBlocking 안에 launch를 이용
fun main() = runBlocking { // this: CoroutineScope
launch {
// launch new coroutine in the scope of runBlocking
delay(1000L)
println("World!")
}
println("Hello,")
}
// 예시2
fun test4_2() = runBlocking {
launch {
delay(1000L)
Log.d("Woongs", "Structured Concurrency 1")
}
launch {
delay(1000L)
Log.d("Woongs", "Structured Concurrency 2")
}
launch {
delay(1000L)
Log.d("Woongs", "Structured Concurrency 3")
}
launch {
delay(1000L)
Log.d("Woongs", "Structured Concurrency 4")
}
Log.d("Woongs", "main")
}
* 일시정지, 재개되는지 확인해보기
runBlocking {
launch {
repeat(5) { i ->
println("Coroutine A , $i")
btn_02Text = btn_02Text+"\nCoroutine A , $i"
delay(10L)
}
}
launch {
repeat(5) { i ->
println("Coroutine B , $i")
btn_02Text = btn_02Text+"\nCoroutine B , $i"
delay(10L)
}
}
println("Coroutine Outer")
btn_02Text = btn_02Text+"\nCoroutine Outer"
}
참고
https://kotlinlang.org/docs/coroutines-basics.html#scope-builder
https://eso0609.tistory.com/73?category=824962
https://www.youtube.com/watch?v=14AGUuh8Bp8&list=PLbJr8hAHHCP5N6Lsot8SAnC28SoxwAU5A&index=2
'Android 공부 > Coroutine' 카테고리의 다른 글
[XX캠퍼스] 02. Kotlin Coroutines & Flow ( 잡,구조화된동시성 ) (0) | 2022.07.20 |
---|---|
[XX캠퍼스] 01. Kotlin Coroutines & Flow ( 스코프빌더 ) (0) | 2022.07.19 |
코루틴 Flow 참고 블로그 주소 (0) | 2022.07.16 |
코루틴 기초 정리 _ part 02 Cancellation And Timeouts (0) | 2022.07.16 |
(스크랩) 코루틴 이란? (0) | 2020.12.23 |