【Kotlin 协程】协程启动 ② ( 多协程控制 | launch 协程执行顺序控制 | Job#join() 函数 | async 协程执行顺序控制 | Deferred#await() 函数 )


源码地址 : https://download.csdn.net/download/han1202012/87183425





一、launch 协程执行顺序控制



如果需要通过 launch 协程构建器 启动多个协程 , 后面的协程需要等待前面的协程执行完毕 , 在启动靠后的协程 , 实现方案如下 :

调用 Job#join() 函数 , 可以挂起协程 , 等待 launch 中协程体内的任务执行完毕 , 再执行后面的协程任务 ;

代码示例 : 下面的代码中 , 先执行 launchJob 协程 , 调用 launchJob.join() 函数会挂起协程 , 该 launchJob 协程任务执行完毕后 , 才会执行后面的 launch 协程任务 ;

runBlocking {
    // 调用 runBlocking 函数 , 可以将 主线程 包装成 协程
    val launchJob = launch {
        // 调用该挂起函数延迟 100 ms
        delay(100)
        Log.i(TAG, "launchJob 执行完毕")
    }
    // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
    launchJob.join()
    
    val launchJob1 = launch {
        // 调用该挂起函数延迟 100 ms
        delay(100)
        Log.i(TAG, "launchJob1 执行完毕")
    }
}

Job#join() 函数原型如下 : 该函数是挂起函数 , 不会阻塞主线程 ;

/**
 * 挂起协程,直到此作业完成。此调用正常恢复(没有异常)
 * 当作业因任何原因完成且调用协程的[job]仍为[active][isActive]时。
 * 这个函数也[启动][Job。如果[Job]仍然处于_new_状态,则启动]相应的协程。
 *
 * 注意,只有当所有子任务都完成时,作业才算完成。
 *
 * 这个挂起函数是可取消的,并且**总是**检查是否取消了调用协程的Job。
 * 如果调用协程的[Job]被取消或完成
 * 函数被调用,或当它被挂起时,此函数
 * 把[CancellationException]。
 *
 * 特别是,它意味着父协程在子协程上调用' join '时抛出
 * [CancellationException]如果子进程失败,因为子进程的失败会默认取消父进程,
 * 除非子进程是从[supervisor orscope]内部启动的。
 *
 * 此函数可用于带有[onJoin]子句的[select]调用。
 * 使用[isCompleted]检查该作业是否已完成,无需等待。
 *
 * 有一个[cancelAndJoin]函数,它结合了[cancel]和' join '的调用。
 */
public suspend fun join()


源码地址 : https://download.csdn.net/download/han1202012/87183425


完整代码示例 :

package kim.hsl.coroutine

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity(){
    val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            // 调用 runBlocking 函数 , 可以将 主线程 包装成 协程

            val launchJob = launch {
                // 调用该挂起函数延迟 100 ms
                delay(100)
                Log.i(TAG, "launchJob 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            launchJob.join()

            val launchJob1 = launch {
                // 调用该挂起函数延迟 100 ms
                delay(50)
                Log.i(TAG, "launchJob1 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            launchJob1.join()

            val launchJob2 = launch {
                // 调用该挂起函数延迟 100 ms
                delay(10)
                Log.i(TAG, "launchJob2 执行完毕")
            }
        }
    }
}

在这里插入图片描述





二、async 协程执行顺序控制



如果需要通过 async 协程构建器 启动多个协程 , 后面的协程需要等待前面的协程执行完毕 , 在启动靠后的协程 , 实现方案如下 :

调用 Deferred#await() 函数 , 可以挂起协程 , 等待 async 中协程体内的任务执行完毕 , 再执行后面的协程任务 ;

代码示例 : 下面的代码中 , 先执行 asyncDeferred 协程 , 调用 asyncDeferred.await() 函数会挂起协程 , 该 asyncDeferred 协程任务执行完毕后 , 才会执行后面的 async 协程任务 ;

runBlocking {
    // 调用 runBlocking 函数 , 可以将 主线程 包装成 协程
    val asyncDeferred = async {
        // 调用该挂起函数延迟 100 ms
        delay(100)
        Log.i(TAG, "asyncDeferred 执行完毕")
    }
    // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
    asyncDeferred.await()
    val asyncDeferred1 = async {
        // 调用该挂起函数延迟 100 ms
        delay(50)
        Log.i(TAG, "asyncDeferred1 执行完毕")
    }
}

Deferred#await() 函数原型如下 : 该函数是挂起函数 , 不会阻塞主线程 ;

/**
 * 在不阻塞线程的情况下等待该值的完成,并在延迟的计算完成时恢复,
 * 返回结果值,如果取消了延迟,则抛出相应的异常。
 *
 * 这个暂停功能是可以取消的。
 * 如果当前协程的[Job]在此挂起函数等待时被取消或完成,则此函数
 * 立即恢复[CancellationException]。
 * 有**立即取消的保证**。如果在此函数被取消时作业被取消
 * 挂起后,它将无法成功恢复。有关底层细节,请参阅[suspendCancellableCoroutine]文档。
 *
 * 这个函数可以在[select]调用和[onAwait]子句中使用。
 * 使用[isCompleted]检查这个延迟值是否已经完成,无需等待。
 */
public suspend fun await(): T


源码地址 : https://download.csdn.net/download/han1202012/87183425


完整代码示例 :

package kim.hsl.coroutine

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity(){
    val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            // 调用 runBlocking 函数 , 可以将 主线程 包装成 协程

            val asyncDeferred = async {
                // 调用该挂起函数延迟 100 ms
                delay(100)
                Log.i(TAG, "asyncDeferred 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            asyncDeferred.await()

            val asyncDeferred1 = async {
                // 调用该挂起函数延迟 100 ms
                delay(50)
                Log.i(TAG, "asyncDeferred1 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            asyncDeferred1.await()

            val asyncDeferred2 = async {
                // 调用该挂起函数延迟 100 ms
                delay(10)
                Log.i(TAG, "asyncDeferred2 执行完毕")
            }
        }
    }
}

执行结果 :

在这里插入图片描述





三、完整代码




源码地址 : https://download.csdn.net/download/han1202012/87183425


package kim.hsl.coroutine

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivity : AppCompatActivity(){
    val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        runBlocking {
            // 调用 runBlocking 函数 , 可以将 主线程 包装成 协程

            val launchJob = launch {
                // 调用该挂起函数延迟 100 ms
                delay(100)
                Log.i(TAG, "launchJob 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            launchJob.join()

            val launchJob1 = launch {
                // 调用该挂起函数延迟 100 ms
                delay(50)
                Log.i(TAG, "launchJob1 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            launchJob1.join()

            val launchJob2 = launch {
                // 调用该挂起函数延迟 100 ms
                delay(10)
                Log.i(TAG, "launchJob2 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            launchJob2.join()



            val asyncDeferred = async {
                // 调用该挂起函数延迟 100 ms
                delay(100)
                Log.i(TAG, "asyncDeferred 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            asyncDeferred.await()

            val asyncDeferred1 = async {
                // 调用该挂起函数延迟 100 ms
                delay(50)
                Log.i(TAG, "asyncDeferred1 执行完毕")
            }
            // 挂起协程 , 等待协程执行完毕会后再执行后面的协程任务
            asyncDeferred1.await()

            val asyncDeferred2 = async {
                // 调用该挂起函数延迟 100 ms
                delay(10)
                Log.i(TAG, "asyncDeferred2 执行完毕")
            }
        }
    }
}

执行结果 :

23:09:21.239  I  launchJob 执行完毕
23:09:21.298  I  launchJob1 执行完毕
23:09:21.331  I  launchJob2 执行完毕
23:09:21.471  I  asyncDeferred 执行完毕
23:09:21.562  I  asyncDeferred1 执行完毕
23:09:21.611  I  asyncDeferred2 执行完毕

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值