코루틴을 사용하기 전 의존성을 추가해야한다.
dendendcies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3")
testImplementation(kotlin("test))
}
runBlocking
- 코루틴을 생성하는 코루틴 빌더.
- runBlocking으로 감싼 코드는 코루틴 내부의 코드가 수행이 끝날 때까지 스레드가 블록킹된다.
fun main() {
runBlocking {
println("hello")
println(Thread.currentThread().name)
}
println("world")
println(Thread.currentThread().name)
}
// Hello
// main @coroutine#1
// world
// main
// 둘다 main thread 이지만 코루틴 블럭에서 실행된 코드는 스레드에 coroutine 수식어가 붙어있다.
// 이를 확인하려면 - d 를 누른 후 kotlinx coroutines debug 옵션을 넣자.
// runBlocking 실행이 끝나야 다음 코드가 읽힌다.
// 잘 쓰이지 않는다.
launch
- 스레드 차단 없이 새 코루틴을 시작하고 결과로 잡이라 하는 결과를 반환하는 코루틴 빌더
- 실행에 대한 흐름 조절 가능
- 단, 비동기 처리에 대한 결과를 가져오는것은 불가
fun main() = runBlocking<Unit> {
launch {
delay(500) // 코루틴 라이브러리에서 정의된 일시중단. 스레드를 블록킹하지 않음.
// Thread.sleep(500) 스레드를 블록킹 함
println("world")
}
println("hello")
}
// hello
// world
fun main() = runBlocking<Unit> {
val job1: Job = launch {
val elapsedTime = measureTimeMillis {
delay(150)
}
println("async task-1 $elapsedTime ms")
}
job1.cancel()
val job2: Job = launch {
val elapsedTime = measureTimeMillis {
delay(100)
}
println("async task-2 $elapsedTime ms")
}
val job3: Job = launch(start=CoroutineStart.LAZY) {
val elapsedTime = measureTimeMillis {
delay(100)
}
println("async task-3 $elapsedTime ms")
}
println("start task-3")
job3.start()
}
async builder
- 비동기 작업을 통해서 결과를 만들어 낼 때 사용
- 비동기 처리를 할 때 async 함수를 사용하고 결과를 받아올 때는 await 을 사용해주면 된다.
- 병렬 처리도 가능하다
- 반환 타입은 Deffered<T> 로 되어 있으며, Deffered 내부에는 결과를 받아올 수 있는 await을 제공하고 있다.
fun sum(a: Intm b:Int) = a + b
fun main() = runBlocking<Unit> {
val result1: Deffered<Int> = async {
delay(100)
sum(1,3)
}
println("result1 : ${result1.await()}")
val result2 = async {
delay(100)
sum(2,5)
}
println("result2 : ${result2.await()}")
}
suspend
- 코루틴의 핵심 요소로 일시 중단이 가능한 함수를 말한다.
- suspend 함수는 일반 함수를 마음껏 호출할 수 있지만 일반 함수에선 suspend 함수를 일반적으로는 바로 호출 불가능
- 호출을 위해 runblocking 을 사용하던지, 호출함수가 suspend 가 되어야 한다.
- suspend 함수에서 async, launch 와 같은 코루틴 빌더를 사용하려면 coroutineScope를 사용해야 한다.
- coroutineScope 와 runblocking 의 다른점은 coroutineScope 은 현재 스레드가 차단되지 않는다 (논블록킹)
suspend fun main() {
doSomething()
}
fun printHello() = println("hello")
suspend fun doSomething() = coroutineScope {
laynch {
delay(200)
println("world")
}
laynch {
printHello()
}
}
flow
- 코루틴에서 리액티브 프로그래밍 스타일로 작성할 수 있도록 만들어진 API
- suspend 함수의 경우 reactor Mono 처럼 단일 값을 비동기로 반환하지만 flow을 사용하게되면 reactor Flux 처럼 여러 개의 값을 반환할 수 있다.
- flow 도 리액티브 스타일처럼 최종 연산자인 collect 를 호출해 줘야만 이 코드가 동작한다.
fun main() = runBlocking<Unit> {
val flow = simple()
flow.collect{ value -> println(value) }
}
fun simpel(): Flow<Int> = flow {
println("flow started")
for(i in 1..3) {
delay(100)
emit(i) // 데이터 통지
}
}