Kotlin协程的launch与async
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,
interface Deferred<out T> : Job (source)
另外,async默认启动协程后立即执行,但是也可以通过参数指定启动方式为CoroutineStart.LAZY,此时只有调用了await时,才会启动协程。
总结
当需要同步获取子协程的执行结果时使用async,不关心子协程的处理结果时使用launch。可以类比到线程中Thread/Runable和Future/Callable在使用场景的区别。