协程学习(四)协程简单的使用 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 挂起被恢复后也被执行了

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

相关推荐
alexhilton7 小时前
模块化Jetpack Compose架构
android·kotlin·android jetpack
厮年断弦9 小时前
AI 辅助开发实录:一周做完一个 Android 本地音乐播放器,这些坑替你踩了
android
hai_android9 小时前
InputStage 责任链核心执行流程
android·android studio·android jetpack
mmsx12 小时前
Android 测绘计算工程化:七四参数、高程拟合与单位系统
android·kotlin
我是场14 小时前
我的NPI项目之-Touch的EE特性
android·arm开发
天空之城--14 小时前
Android一周动态:AI编程、Compose与车载生态新信号
android·flutter
恋猫de小郭15 小时前
Dart 4.0 要彻底移除 dart:mirrors,Augmentations 应该要来了
android·前端·flutter
Carson带你学Android16 小时前
Gemini 4 Argon 发布:对 Android 开发者意味着什么?
android·ai编程
事圆则缓17 小时前
Kotlin Flow、StateFlow、SharedFlow 全解析:冷流、热流与 Android 状态管理
android·kotlin·php
应用市场17 小时前
把旧 Pixel 变成相册备份中转站(上):Mac 到安卓的照片传输工具设计——流式上传、sha256 校验、adb forward 与 Bonjour
android·macos·adb·kotlin·swift