文章目录
概要
在讲协程并发操作async、await用法前,先提一下协程的定义:协程是一种轻量级的并发编程机制,基于suspend挂起函数实现,它可以在函数执行时,暂停协程块内的后续代码的执行,等异步任务执行结束再执行。实现了同步的方式处理异步任务。
async、await源码分析
async方法返回结果是Deferred,这个Deferred又是Job的子类。async源码如下:
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyDeferredCoroutine(newContext, block) else
DeferredCoroutine<T>(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
await是Deferred接口的一个方法:
public interface Deferred<out T> : Job {
public suspend fun await(): T
public val onAwait: SelectClause1<T>
@ExperimentalCoroutinesApi
public fun getCompleted(): T
@ExperimentalCoroutinesApi
public fun getCompletionExceptionOrNull(): Throwable?
}
用法实例及过程分析
package com.techme.jetpack
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
///协程之并发操作
fun main() {
GlobalScope.launch {
//2.进入协程块,开始running
println("GlobalScope.launch is running:${
System.currentTimeMillis()}")
val result1 = request1()
//4.result1 执行结束
println("$result1:${
System.currentTimeMillis()}")
val deferred2 = async {
request2() }
val deferred3 = async {
request3() }
// 7.request2和request3并发执行结束,更新ui。
println("update UI ${
deferred2.await()},${
deferred3.await()}:${
System.currentTimeMillis()}")
}
//1.先执行主线程的任务
println("main Thread:${
System.currentTimeMillis()}")
Thread.sleep(6000)//主线程休眠6000(即协程内挂起函数休眠的总和),为了确保协程内的任务执行完。
}
suspend fun request3(): String {
//6.call request3
println("call request3:${
System.currentTimeMillis()}")
delay(3000)
return "result3"
}
suspend fun request2(): String {
//5.call request2
println("call request2:${
System.currentTimeMillis()}")
delay(2000)
return "result2"
}
suspend fun request1(): String {
//3.call request1
println("call request1:${
System.currentTimeMillis()}")
delay(1000)
return "result1"
}
运行打印结果:
main Thread:1701915880220 //1.先执行主线的任务
GlobalScope.launch is running:1701915880235 //2.进入协程块,开始running
call request1:1701915880237//3.call request1
result1:1701915881269//4.result1请求结果,result1 执行的时间 1701915881269-1701915880237=1032
call request2:1701915881276//5.call request2
call request3:1701915881289//6.call request3
update UI result2,result3:1701915884303//7.request2和request3并发执行结束。request2执行时间:1701915884303-1701915881276=3027 request3执行时间:1701915884303-1701915881289=3014,request2和request3总的执行时间差不多3000,若是串行的话request2和request3的总执行时间应该差不多5000,因此属于并发执行,增强了任务间协同。
Process finished with exit code 0//8.结束
小结
async启动一个新的协程,返回一个Deferred对象,通过Deferred的await方法获取协程执行的结果。
相比传统的线程机制,协程的优势:
- 更加轻量级:协程的创建和销毁比线程更加轻量级,可以更加高效的利用系统资源。
- 更加灵活:协程的执行过程可以被暂停和恢复,可以更加方便的处理异步任务。
- 更加安全:协程避免了线程的竞态条件和死锁等问题,可以更加安全的进行并发编程。