【Kotlin】协程并发操作之async、await用法

概要

在讲协程并发操作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方法获取协程执行的结果。

相比传统的线程机制,协程的优势:

  1. 更加轻量级:协程的创建和销毁比线程更加轻量级,可以更加高效的利用系统资源。
  2. 更加灵活:协程的执行过程可以被暂停和恢复,可以更加方便的处理异步任务。
  3. 更加安全:协程避免了线程的竞态条件和死锁等问题,可以更加安全的进行并发编程。

猜你喜欢

转载自blog.csdn.net/luozegang86/article/details/134849178