当前位置:嗨网首页>书籍在线阅读

16-异步并发执行

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

12.4.2 异步并发执行

如果两个挂起函数之间没有时序上的依赖关系,而且希望通过并发地执行这两个函数来提高执行效率,还可以使用异步的方式来执行。使用异步方式调用时,会用到一个异步函数async,它位于kotlinx.coroutines库中。

fun <T> async(block: suspend () -> T)

严格来说,async只是一个普通函数而不是挂起函数,但是它的block参数带有一个suspend修饰的函数类型suspend () -> T。因此,当将一个Lambda表达式传给async函数时,它需要一个挂起Lambda表达式。代码如下。

async {
    doSomething(foo)
    …
}

从概念上来讲,async函数与launch函数一样,都可以启动一个单独的协程。不同的是,launch函数返回一个不含任何结果的值,而async函数返回一个延迟任务对象Deferred,一种轻量级非阻塞的Future,它表示会在后面提供结果值,可以使用await函数来获取具体的返回结果。

fun main(args: Array<String>) = runBlocking{
    val time = measureTimeMillis {
        //使用async()异步协程
        val one = async(CommonPool) { asynOne() }
        val two = async(CommonPool) {  asynTwo() }
        //使用await()获取协程返回值
        println("result is ${one.await() + two.await()}")
    }
    println("Total time is ${time}")
}
suspend fun asynOne(): Int {
    delay(1000)
    return 3
}
suspend fun asynTwo(): Int {
    delay(2000)
    return 5
}

运行上面的代码,输出的结果如下。

result is 8
Total time is 2022

可以发现,执行两个相同的挂起函数时,异步并发方式比传统的顺序执行效率更高。Deferred接口定义如下。

public interface Deferred<out T> : Job {
    val isCompletedExceptionally: Boolean
    val isCancelled: Boolean
    public suspend fun await(): T
    public fun <R> registerSelectAwait(select: SelectInstance<R>, block: suspend (T) -> R)
    public fun getCompleted(): T
    @Deprecated(message = "Use `isActive`", replaceWith = ReplaceWith("isActive"))
    public val isComputing: Boolean get() = isActive
}

延迟任务Deferred对象属于Job类型,它继承自Job,具有isCompleted、isActive等属性和join、cancel等函数。当然也可以在需要时直接取消它,其中,Deferred对象的常见属性和函数说明如下。

  • isCompletedExceptionally:当协程在计算过程中出现异常failed或被取消时,返回true,此时isActive为false,isCompleted为true。
  • isCancelled:如果当前延迟任务被取消,返回true;否则返回false。
  • await:等待延迟任务完成,如果延迟任务完成,则返回结果值或者相应的异常。

在这当中,延迟任务对象Deferred的状态与对应的属性值如表12-3所示。

表12-3 Deferred状态属性表

| 状态 | isActive | isCompleted | isCompletedExceptionally | isCancelled | | :----- | :----- | :----- | :----- | :----- | :----- | :----- | | New | false | false | false | false | | Active | true | false | false | false | | Resolved | false | true | false | false | | Failed | false | true | true | false | | Cancelled | false | true | true | true |

除此之外,async函数还提供了一个懒加载的选项CoroutineStart.LAYZ参数,该参数表示等待await执行或者启动函数被调用。