runBlocking
은 새로운 코루틴을 만든다.fun main(): Unit = runBlocking {
}
fun main() {
runBlocking {
printWithThread("START")
launch {
delay(2_000L) // 코루틴을 지정 시간 동안 지연시킴
printWithThread("LAUNCH END")
}
}
printWithThread("END")
}
[main] START
[main] LAUNCH END
[main] END
runBlocking
코루틴이 모두 실행될 때까지는 출력될 수 없다.runBlocking
은 이처럼 스레드를 블락시키기에 프로그램에 진입하는 최초 진입 함수나 테스트 코드를 시작할 때만 쓰는 것이 좋다.runBlocking
과 다르게 코루틴을 제어할 수 있는 객체 Job
을 반환 받는다.
CoroutineStart.LAZY
옵션을 주면 job.start()
를 호출할 때까지 실행되지 않는다.
fun main(): Unit = runBlocking {
val job = launch(start = CoroutineStart.LAZY) {
printWithThread("Hello launch")
}
delay(1_000L)
job.start()
}
cancel()
함수로 코루틴을 취소시킬 수도 있다.
fun main(): Unit = runBlocking {
val job = launch {
(1..5).forEach {
printWithThread(it)
delay(500) // 1초에 2까지 출력
}
}
delay(1_000L) // 1초 기다리고
job.cancel() // cancel 호출
}
join()
으로 코루틴이 끝날 때까지 대기할 수도 있다.job1
이 실행되고 delay
시작job1
이 대기하는 순간 job2
가 시작job1
과 job2
가 함께 대기job1
의 대기가 먼저 끝나고 “Job1” 출력job2
의 대기가 끝나거 “Job 2” 출력fun main(): Unit = runBlocking {
val job1 = launch {
delay(1_000)
printWithThread("Job 1")
}
val job2 = launch {
delay(1_000)
printWithThread("Job 2")
} }
join
을 쓰면 job1
이 끝날 때까지 job2
를 기다리게 할 수 있다.fun main(): Unit = runBlocking {
val job1 = launch {
delay(1_000)
printWithThread("Job 1")
}
job1.join() // job1이 끝날 때까지 기다림
val job2 = launch {
delay(1_000)
printWithThread("Job 2")
} }
async
는 launch
와 유사하지만 실행 결과를 반환할 수 있다는 점이 launch
와 다르다.fun main(): Unit = runBlocking {
val job = async {
3 + 5
}
}
async
는 Defferred
객체를 반환한다.
Job
의 하위 타입Job
의 메서드들을 똑같이 가지며 추가로 await()
메서드를 가진다.fun main(): Unit = runBlocking {
val job = async {
3 + 5
}
}
val eight = job.await() // 변수에 8이 담긴다.
async
는 여러 api를 동시에 호출하여 소요시간을 최소화할 수 있다.suspend fun
인 delay
를 호출하기 위해 suspend fun
을 사용suspend fun apiCall1(): Int {
delay(1_000L)
return 1
}
suspend fun apiCall2(): Int {
delay(1_000L)
return 2
}
await
사용으로 두 api를 거의 동시에 호출하고 결과를 합칠 수 있다.fun main(): Unit = runBlocking {
val time = measureTimeMillis {
val job1 = async { apiCall1() }
val job2 = async { apiCall2() }
printWithThread(job1.await() + job2.await())
}
printWithThread("소요 시간 : $time ms") // 1000ms 조금 넘는 시간이 걸림
}
async
는 callback
을 사용하지 않고도 동기 방식으로 코드를 작성할 수 있게 해준다.
apiCall2()
메서드가 apiCall1()
메서드의 결과를 파라미터로 받아야 하는 경우callback
지옥에 빠지지 않고 코드를 작성할 수 있다.fun main(): Unit = runBlocking {
val time = measureTimeMillis {
val job1 = async { apiCall1() }
val job2 = async { apiCall2(job1.await()) }
printWithThread(job2.await())
}
printWithThread("소요 시간 : $time ms") // 2000ms 조금 넘는 시간
}
CoroutineStart.Lazy
옵션을 async
와 함께 쓰면 await
함수를 호출했을 때 계산 결과를 계속 기다리게 된다.fun main(): Unit = runBlocking {
val time = measureTimeMillis {
val job1 = async(start = CoroutineStart.LAZY) { apiCall1() }
val job2 = async(start = CoroutineStart.LAZY) { apiCall2() }
printWithThread(job1.await() + job2.await())
}
printWithThread("소요 시간 : $time ms") // 2000ms 조금 넘는 시간
}
CoroutineStart.Lazy
옵션을 사용하고 싶다면 start
를 미리 호출해주면 된다.fun main(): Unit = runBlocking {
val time = measureTimeMillis {
val job1 = async(start = CoroutineStart.LAZY) { apiCall1() }
val job2 = async(start = CoroutineStart.LAZY) { apiCall2() }
printWithThread(job1.await() + job2.await())
}
job1.start()
job2.start()
printWithThread("소요 시간 : $time ms") // 1000ms 조금 넘는 시간
}