Composing suspending functions
14490 단어 kotlinCoroutinesCoroutines
Sequential by default
- 기본적으로 suspend function은 sequential하게 작동한다.
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, too
return 29
}
val time = measureTimeMillis {
val one = doSomethingUsefulOne() // 1 second
val two = doSomethingUsefulTwo() // 1 second
println("The answer is ${one + two}")
}
println("Completed in $time ms") // prints 2 seconds
Concurrent using async
- 위 예제에서
doSomethingUsefulOne()
와doSomethingUsefulTwo()
가 dependency가 없다면 동시에 실행되도 될 것이다. - 이때
Deferred<T>
를 반환하는async
coroutine builder와await()
함수를 쓰면 된다. - 이는
Job
을 반환하는launch
와join()
의 관계와 같다.
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
Lazily started async
- 위의 async 예제에서는 async가 있는 라인에서 바로 실행되었다.
- 이것을 lazy하게 선언만 했다가 나중에 실행시킬 수도 있다.
async
의start
parameter에CoroutineStart.LAZY
를 줘서 설정할 수 있다.start
에 줄 수 있는 parameter는 CoroutineStart 문서를 보자.
val time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
// some computation
one.start() // start the first one
two.start() // start the second one
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
- 참고로 위 코드에서
start()
하지 않으면 sequential하게 동작한다. (wait()
에 걸림)
Async-style functions
doSomethingUsefulOne()
와doSomethingUsefulTwo()
를 아래처럼 바꿔서 asynchronous하게 할 수도 있다.
fun somethingUsefulOneAsync() = GlobalScope.async {
doSomethingUsefulOne()
}
- 물론 GlobalScope를 이유없이 남발하는 것은 지양해야하므로 아래 방법을 살펴보자.
Structured concurrency with async
- 그럼 이번에는 structured concurrency를 활용한다.
suspend fun concurrentSum(): Int = coroutineScope {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
one.await() + two.await()
}
fun main() = runBlocking {
val time = measureTimeMillis {
println("The answer is ${concurrentSum()}")
}
println("Completed in $time ms")
}
- 이렇게 하면,
concurrentSum()
에서 예외가 나도 scope내의 코루틴은 모두 cancel될 것이다. (GlobalScope였다면 그렇지 않을 것이다.) - cancel해서 exception을 내고 진행중인 coroutine이 cancel되는 아래 예제를 보자.
suspend fun failedConcurrentSum(): Int = coroutineScope {
val one = async {
try {
delay(Long.MAX_VALUE) // Emulates very long computation
42
} finally {
println("First child was cancelled")
}
}
val two = async<Int> {
println("Second child throws an exception")
throw ArithmeticException()
}
one.await() + two.await()
}
Author And Source
이 문제에 관하여(Composing suspending functions), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@cmplxn/Composing-suspending-functions저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)