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在使用场景的区别。

经验分享 程序员 微信小程序 职场和发展