Kotlin中启动协程的方式常用的有两种:launch/join以及async/await。这两种方式有什么区别呢?
launch
launch用来启动一个子协程并立即返回,协程像线程一样异步执行。协程中的未捕获异常会导致进程的crash。launch返回一个Job对象,通过Job.join方法可以同步等待协程的完成,就像thread的join一样。
fun main(args: Array<String>) {
launch { // launch new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch { // launch new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
}
async
async用来启动一个协程并返回一个Deferred,使用Deffered.await可以获取async返回的结果,所以async相当于可以返回结果的launch。async内的代码中未捕获异常不会造成进程crash,而是会被储存到Deferred中返回。
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
Deferred实际上也是一个Job,https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html
interface Deferred<out T> : Job (source)
另外,async默认启动协程后立即执行,但是也可以通过参数指定启动方式为CoroutineStart.LAZY,此时只有调用了await时,才会启动协程。
总结
当需要同步获取子协程的执行结果时使用async,不关心子协程的处理结果时使用launch。可以类比到线程中Thread/Runable和Future/Callable在使用场景的区别。