이론
처음 들었을 때는 Kotlin에서 만들고 사용되는 기술이라고 생각했었다.
하지만 1958년에 코루틴 용어가 만들어지고 어셈블리 프로그램에서 적용되었으며 다른 다양한 프로그래밍 언어에서 지원한다고한다.
찾아보면서 출력 시간 지연할 때 사용했었나 했지만 그건 스레드였다...
코루틴은
"실행의 지연과 재개를 허용함으로써, 비선점적 멀티태스킹을 위한 서브 루틴을 일반화한 컴퓨터 프로그램 구성요소"
라고 한다.
비선점적 ?
하나의 프로세스가 cpu를 할당받으면 종료되기 전까지 다른 프로레스를 강제로 차지할 수 없다.
루틴 ?
프로그래밍에서 루틴은 프로그램의 흐름을 추상적으로 일컫는 말이다.
프로그램은 메인 루틴과 서브 루틴으로 나뉜다.
예를 들어 main함수에 의해 수행되는 프로그램의 흐름을 메인 루틴이라고 한다면 main함수 안에서 실행되는 개별 함수들에 의해 수행되는 흐름을 서브 루틴이라고 비유한다.
루틴의 종류 중 하나인 함수는 호출을 함으로써 그 내부에 진입하여 내부에서 처리를 수행하고, 처리가 끝나면 함수도 종료되는 구조를 가지고 있기 때문에 보통은 일직선적인 흐름을 가지고 있다고 할 수 있다.
하지만 코루틴의 특징은 이 일직선적인 흐름을 지연시켰다가 다시 재시작이 가능하다. 그렇기 때문에 비동기 프로그래밍이 가능하게 된다.
간단 설명
- 코루틴은 스레드와 기능적으로 비슷하지만 하나의 스레드 안에 여러 개의 코루틴이 실행되는 개념으로 비동기 프로그래밍에 권장되는 동시 실행 설계 패턴이다.
- 단일 쓰레드 내에서 여러 개의 코루틴을 실행할 수 있기 때문에 많은 양의 동시 작업을 처리할 수 있으면서 메모리 절약의 장점이 있다.
- 코루틴은 스레드가 아닌 루틴을 일시 중단(suspend)하는 방식이라 Context-Switching에 비용이 들지 않는다.
Kotlin 코루틴 구조
크게 Coroutine Scope, Coroutine Context, Coroutine Builder 이렇게 세 부분으로 나눌 수 있다.
1. Coroutine Scope
코루틴의 동작하는 범위를 규정한다. 스코프 내에서 실행되는 코루틴의 실행을 감시하거나 취소할 수 있다.
GlobalScop는 CoroutineScope의 한 종류이다. 안드로이드에서 어플리케이션 라이프리사이클을 따르며, 싱글톤으로 최사위 레벨에서 코루틴을 시작하기 때문에 필요할때 만들어 쓰고 버린다는 사용법이 불가능하다.
일반적으로는 사용자체를 추천하지 않는다.
간단 설명 : 코루틴이 실행되는 범위이다.
2.Coroutine Context
코루틴은 항상 Coroutine Context로 구성된 콘텍스트 안에서 실행되는데, 이 콘테스트는 Dispatchers와 Job으로 구성된다.
- Dispatchers.Default
- CPU 사용량이 많은 무거운 작업 처리에 최적화 되어 있습니다.
예를 들어, 데이터를 가공하거나 복잡한 연산, JSON 파싱을 할 때 주로 사용됩니다.
- CPU 사용량이 많은 무거운 작업 처리에 최적화 되어 있습니다.
- Dispachers.IO
- 파일 혹은 소켓IO등의 가볍고 빈번한 IO작업에 사용한다.
- Blocking IO용 공유 스레드풀에서 동작한다.
- 필요에 따라 스레드를 추가 생성하거나 없앨 수 있는데 64 OR 코어 수 중 큰 수 만큼 생성이 가능하다.
- Dispatchers.Default와 스레드를 공유하므로 withContext에서 Dispatcher 변경시 context switching하지 않고 동일한 스레드에서 실행이 된다.
- 예를 들어, Retrofit으로 네트워크 통신을 하거나, File이나 Room 데이터베이스에서 데이터를 읽고/쓸 때 사용됩니다.
- Dispatchers.Main
- 안드로이드의 메인 쓰레드로, UI 작업을 위해 사용해야 합니다.예를 들어, UI를 구성하거나 LiveData를 업데이트 할 때 사용됩니다.
- Dispatchers.Unconfined
- 첫번째 지연점까지만 실행된다.
- 메인스레드에서 동작한다.
- 일반적인 용도로는 사용하지 않는다.
간단 설명 : 코루틴 작업을 어떤 스레드에서 실행할 것인지에 대한 동작을 정의하고 제어하는 요소
3. Coroutine Builder
간단 설명 : 코루틴을 실행시켜주는 함수이다.
코루틴을 시작하는 방법에는 4가지가 있다.
- launch: 메인 스레드를 블록하지 않는 코루틴 작업을 실행한다. 결과를 반환할 필요가 없는 작업에 사용하며 Job 객체를 반환한다.
- async: 메인 스레드를 블록하지 않는 코루틴 작업을 실행한다. 결과를 반환할 필요가 있는 작업에 사용하며 Deferred 객체를 반환한다.
- runBlocking: 메인 스레드를 블록하고 작업을 실행한다. runBlocking은 테스트 용도 등 에나 사용하지, 코루틴을 위해서는 사용하지 말라고 권장하고 있다.
- withContext: 예를들어 Dispatchers.Main으로 지정된 스코프 안에서 Dispatchers.IO가 필요한 처리를 해야할 일이 있을 수 있다. 이때 Dispatchers안에 다시 Dispatchers를 정의할 수도 있지만 withContext를 사용하면 Dispatchers를 간편하게 스위치 할 수 있다. withContext를 이용한 스코프전환은 OS에서 관리되므로 오버헤드가 적다고 알려져 있다.
+ susfend funtion
코루틴 안에서만 실행할 수 있는 코루틴 전용 메서드이다.
메소드명 앞에 suspend를 붙여야한다.
사용
예제 1)
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
launch {
delay(1000L)
println("World!")
}
println("Hello")
}
출력 :
Hello
//(1초 뒤)
World!
설명
launch { } :
코루틴 빌더로 나머지 코드와 동시 실행을 위해 새로운 코루틴을 생성하며 작업을 독립적으로 진행한다. 때문에 Hello가 먼저 출력되었다.
delay() :
delay 는 특별한 일시 정지 기능으로, 특정 시간동안 코루틴을 일시정지 시킨다. 코루틴을 일시 중단하면 기본 스레드가 차단되지 않지만, 다른 코루틴이 코드를 위해 기본 스레드를 실행하고 사용할 수 있다.
runBlocking {} :
runBlocking 도 코루틴 빌더로 fun main()의 코루틴이 아닌 영역과 runBlocking 중괄호 내의 코루틴 코드를 연결한다.
예제 2)
fun main() = runBlocking {
launch { doWorld() }
println("Hello")
}
suspend fun doWorld() {
delay(1000L)
println("World!")
}
//출력 위와 동일
ref
'Kotlin > 문법' 카테고리의 다른 글
Koltin - 날짜 시간 출력 (0) | 2024.03.14 |
---|---|
Kotlin - Pair, Triple (0) | 2024.03.13 |
Scope Functions (영역함수) (0) | 2024.03.07 |
Kotlin - repeat (0) | 2024.02.19 |
Kotlin - startsWith, andsWith (0) | 2024.02.19 |