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

05-协程

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

2.2.3 协程

Kotlin 1.1带来的关键特性之一就是协程,它带来了async/await、 yield 以及类似的编程风格。对于一些耗时的操作(如CPU或GPU密集型任务等),协程提供一种既可避免阻塞又廉价可控的操作方式:协程挂起(coroutine suspension)。协程将复杂的异步操作放入底层库中,程序逻辑可顺序表达,以此来简化异步编程。该底层库可以将用户的代码包装为回调/订阅事件,在不同线程(甚至不同机器)上调度执行。

和线程/进程相比,协程是通过编译技术来实现的,不需要虚拟机VM和操作系统OS的支持。更重要的是,协程挂起可由用户来控制,也无须上下文切换和OS操作。而协程和线程/进程另一个不同的地方是,协程不能在随机指令中挂起,而只能在挂起点(即调用标记函数)挂起。

下面是kotlinx.coroutines 外部库中 async/await的部分实现代码。

// 在后台线程池中运行代码
fun asyncOverlay() = async(CommonPool) {
    // 启动两个异步操作
    val original = asyncLoadImage("original")
    val overlay = asyncLoadImage("overlay")
    // 然后应用叠加到两个结果
    applyOverlay(original.await(), overlay.await())
}
// 在页面上下文中启动新的协程
launch(UI) {
    // 等待异步叠加完成
    val image = asyncOverlay().await()
    // 然后在页面中显示
    showImage(image)
}

在上面的代码中,async函数启动一个协程。当调用asyncOverlay().await()时,挂起执行的协程,转而执行正在等待的操作,在操作完成后协程恢复。

除此之外,通过对yield和yieldAll函数的使用还可以支持惰性生成序列。在生成的序列中,每个元素在被取回前挂起代码块,并在下一次元素请求时恢复。下面是使用yieldAll 函数生成序列的例子。

import kotlin.coroutines.experimental.*
fun main(args: Array<String>) {
    val seq = buildSequence {
       for (i in 1..4) {
          // 产生一个 i 的平方
          yield(i * i)
       }
       // 产生一个区间
       yieldAll(26..28)
    }
    // 输出该序列
    println(seq.toList())
}

上面的例子输出结果如下。

[1, 4, 9, 16, 26, 27, 28]

协程是Kotlin的重要特性之一,本节只是粗略地介绍了协程相关的知识,后面的章节会重点介绍。