协程学习(四)协程简单的使用 coroutineScope 与 supervisorScope

我学习协程的历程

1.协程学习(一)一个最简单的协程例子

2.协程学习(二)协程简单的使用launch async join await

3.协程学习(三)协程简单的使用 CoroutineStart

4.协程学习(四)协程简单的使用 coroutineScope 与 supervisorScope

我们在 协程学习(二) 中遇到一个问题,那就是顺序请求3个接口的问题,我们把这个问题再描述一下

现在有3个接口,要求是顺序的请求这3个接口,

kotlin 复制代码
suspend fun Func1()= withContext(Dispatchers.IO){
    delay(2000)
}

suspend fun Func2()= withContext(Dispatchers.IO){
    delay(1000)
}
suspend fun Func3()= withContext(Dispatchers.IO){
    delay(3000)
}

在这个基础上我们再增加一个逻辑,那就是这3个接口只要有一个接口调用失败,那么所有的接口都不需要等待了,一起失败

这个问题就引出了协程的作用域的概念了

coroutineScope 作用域,子协程中只要有一个协程失败,其他兄弟协程也会失败

案例如下

现在 Func2 是耗时最少的任务,现在让Func2抛出异常看一下结果

scss 复制代码
@JvmStatic
fun main(a:Array<String>) {
    runBlocking {
        coroutineScope {
            launch {
                Func1()
                println("------------Func1执行完毕了-----------")
            }
            launch {
                Func2()
                println("------------Func2执行完毕了-----------")
                throw NullPointerException("抛出异常")
            }
            launch {
                Func3()
                println("------------Func3执行完毕了-----------")
            }
        }
        println("------------coroutineScope parent 执行完毕了-----------")
    }
}
结果:

------------Func2执行完毕了-----------
Exception in thread "main" java.lang.NullPointerException: 抛出异常
	at com.tsm.opencv.TsmTest$main$1$1$2.invokeSuspend(TsmTest.kt:33)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at com.tsm.opencv.TsmTest.main(TsmTest.kt:24)

Process finished with exit code 1

发现只有第二个执行任务执行完成了,任务1 和 任务3执行完成并没有打印就已经退出了, 现在让耗时时间最久的任务3抛出异常

scss 复制代码
@JvmStatic
fun main(a:Array<String>) {
    runBlocking {
        coroutineScope {
            launch {
                Func1()
                println("------------Func1执行完毕了-----------")
            }
            launch {
                Func2()
                println("------------Func2执行完毕了-----------")
            }
            launch {
                Func3()
                println("------------Func3执行完毕了-----------")
                throw NullPointerException("抛出异常")
            }
        }
        println("------------coroutineScope parent 执行完毕了-----------")
    }
}
结果:
------------Func2执行完毕了-----------
------------Func1执行完毕了-----------
------------Func3执行完毕了-----------
Exception in thread "main" java.lang.NullPointerException: 抛出异常
	at com.tsm.opencv.TsmTest$main$1$1$3.invokeSuspend(TsmTest.kt:37)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at com.tsm.opencv.TsmTest.main(TsmTest.kt:24)

Process finished with exit code 1

这里可以看到任务1 2 3 都执行完毕了,但是 coroutineScope 后续代码扔没有执行,至于为什么没有执行就涉及到任务协程的异常捕获的相关问题了,这里只需要知道在使用 coroutineScope 作用域的情况下如果子协程中一个任务失败了,其他兄弟协程也会被取消

supervisorScope 作用域,子协程中有一个协程失败,其他兄弟协程不会受到影响,

我们先让执行速度最慢的任务 3 抛出异常

scss 复制代码
@JvmStatic
fun main(a:Array<String>) {
    runBlocking {
        supervisorScope {
            launch {
                Func1()
                println("------------Func1执行完毕了-----------")
            }
            launch {
                Func2()
                println("------------Func2执行完毕了-----------")
            }
            launch {
                Func3()
                println("------------Func3执行完毕了-----------")
                throw NullPointerException("抛出异常")
            }
        }
        println("------------coroutineScope parent 执行完毕了-----------")
    }
}
结果:

------------Func2执行完毕了-----------
------------Func1执行完毕了-----------
------------Func3执行完毕了-----------
Exception in thread "main" java.lang.NullPointerException: 抛出异常
	at com.tsm.opencv.TsmTest$main$1$1$3.invokeSuspend(TsmTest.kt:37)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at com.tsm.opencv.TsmTest.main(TsmTest.kt:24)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@16f65612, BlockingEventLoop@311d617d]
------------supervisorScope parent 执行完毕了-----------

Process finished with exit code 0

可以看到虽然任务3虽然抛出异常了,但是在 supervisorScope 执行完毕后的打印还是出来了,这与 coroutineScope 表现是不同的,我们继续往耗时最少任务2抛出异常

scss 复制代码
@JvmStatic
fun main(a:Array<String>) {
    runBlocking {
        supervisorScope {
            launch {
                Func1()
                println("------------Func1执行完毕了-----------")
            }
            launch {
                Func2()
                println("------------Func2执行完毕了-----------")
                throw NullPointerException("抛出异常")
            }
            launch {
                Func3()
                println("------------Func3执行完毕了-----------")
            }
        }
        println("------------supervisorScope parent 执行完毕了-----------")
    }
}
结果:
------------Func2执行完毕了-----------
Exception in thread "main" java.lang.NullPointerException: 抛出异常
	at com.tsm.opencv.TsmTest$main$1$1$2.invokeSuspend(TsmTest.kt:33)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:280)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
	at com.tsm.opencv.TsmTest.main(TsmTest.kt:24)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@16f65612, BlockingEventLoop@311d617d]
------------Func1执行完毕了-----------
------------Func3执行完毕了-----------
------------supervisorScope parent 执行完毕了-----------

Process finished with exit code 0

这段代码中虽然耗时最少的任务2在执行完成后抛出异常,但是后续任务 1 与任务3 还是执行完成了,而且 supervisorScope 挂起被恢复后也被执行了

到了这里协程中比较常用协同作用域就介绍完了,但是这里面案例还是有一些问题,那就是异常的处理,关于异常的相关介绍,在后续的文章中会介绍到

相关推荐
尚久龙13 分钟前
安卓学习 之 用户登录界面的简单实现
android·运维·服务器·学习·手机·android studio·安卓
Modu_MrLiu17 分钟前
Android实战进阶 - 启动页
android·实战进阶·启动页·倒计时场景
出门吃三碗饭1 小时前
编译器构造:从零手写汇编与反汇编程序(一)
android·汇编
Just_Paranoid2 小时前
【WorkManager】无法在 Direct Boot 模式下初始化
android·jetpack·usermanager·workmanager·directboot
前端小超超2 小时前
如何配置capacitor 打包的安卓app固定竖屏展示?
android·前端·gitee
顾林海2 小时前
探秘Android JVM TI:虚拟机背后的"隐形管家"
android·面试·性能优化
刘大国3 小时前
<android>反编译魔改安卓系统应用并替换
android
恋猫de小郭4 小时前
Flutter Riverpod 3.0 发布,大规模重构下的全新状态管理框架
android·前端·flutter
纤瘦的鲸鱼4 小时前
MySQL慢查询
android·adb
郭庆汝4 小时前
模型部署:(三)安卓端部署Yolov8-v8.2.99目标检测项目全流程记录
android·yolo·目标检测·yolov8