fun main() = runBlocking<Unit> { try { failedConcurrentSum() } catch(e: ArithmeticException) { println("Computation failed with ArithmeticException") } }
suspend fun failedConcurrentSum(): Int = coroutineScope { val one = async<Int> { 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() }
1 2 3
Second child throws an exception First child was cancelled Computation failed with ArithmeticException
默认顺序执行
2个suspend函数默认是以此执行的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
suspend fun doSomethingUsefulOne(): Int { delay(1000L) return 13 }
suspend fun doSomethingUsefulTwo(): Int { delay(1000L) return 29 }
val time = measureTimeMillis { val one = doSomethingUsefulOne() val two = doSomethingUsefulTwo() println("The answer is ${one + two}") } println("Completed in $time ms")
1 2
The answer is 42 Completed in 2017 ms
使用async并发执行
1 2 3 4 5 6
val time = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms")
public interface CoroutineContext { public abstract fun <R> fold(initial: R, operation: (R, kotlin.coroutines.CoroutineContext.Element) -> R): R
public abstract operator fun <E : kotlin.coroutines.CoroutineContext.Element> get(key: kotlin.coroutines.CoroutineContext.Key<E>): E?
public abstract fun minusKey(key: kotlin.coroutines.CoroutineContext.Key<*>): kotlin.coroutines.CoroutineContext
public open operator fun plus(context: kotlin.coroutines.CoroutineContext): kotlin.coroutines.CoroutineContext { /* compiled code */ }
public interface Element : kotlin.coroutines.CoroutineContext { public abstract val key: kotlin.coroutines.CoroutineContext.Key<*>
public open fun <R> fold(initial: R, operation: (R, kotlin.coroutines.CoroutineContext.Element) -> R): R { /* compiled code */ }
public open operator fun <E : kotlin.coroutines.CoroutineContext.Element> get(key: kotlin.coroutines.CoroutineContext.Key<E>): E? { /* compiled code */ }
public open fun minusKey(key: kotlin.coroutines.CoroutineContext.Key<*>): kotlin.coroutines.CoroutineContext { /* compiled code */ } }
public interface Key<E : kotlin.coroutines.CoroutineContext.Element> { } }
看一个典型的Element
1 2 3 4 5 6 7 8 9 10 11 12
public interface CoroutineExceptionHandler : CoroutineContext.Element { /** * Key for [CoroutineExceptionHandler] instance in the coroutine context. */ public companion object Key : CoroutineContext.Key<CoroutineExceptionHandler>
/** * Handles uncaught [exception] in the given [context]. It is invoked * if coroutine has an uncaught exception. */ public fun handleException(context: CoroutineContext, exception: Throwable) }
launch { // context of the parent, main runBlocking coroutine println("main runBlocking : I'm working in thread ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { // not confined -- will work with main thread println("Unconfined : I'm working in thread ${Thread.currentThread().name}") } launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher println("Default : I'm working in thread ${Thread.currentThread().name}") } launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}") }
1 2 3 4
Unconfined : I'm working in thread main Default : I'm working in thread DefaultDispatcher-worker-1 newSingleThreadContext: I'm working in thread MyOwnThread main runBlocking : I'm working in thread main