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

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

相关推荐
福柯柯15 分钟前
Android ContentProvider的使用
android·contenprovider
不想迷路的小男孩16 分钟前
Android Studio 中Palette跟Component Tree面板消失怎么恢复正常
android·ide·android studio
餐桌上的王子17 分钟前
Android 构建可管理生命周期的应用(一)
android
菠萝加点糖21 分钟前
Android Camera2 + OpenGL离屏渲染示例
android·opengl·camera
用户20187928316732 分钟前
🌟 童话:四大Context徽章诞生记
android
yzpyzp40 分钟前
Android studio在点击运行按钮时执行过程中输出的compileDebugKotlin 这个任务是由gradle执行的吗
android·gradle·android studio
aningxiaoxixi1 小时前
安卓之service
android
TeleostNaCl2 小时前
Android 应用开发 | 一种限制拷贝速率解决因 IO 过高导致系统卡顿的方法
android·经验分享
用户2018792831672 小时前
📜 童话:FileProvider之魔法快递公司的秘密
android
vocal5 小时前
【我的安卓第一课】Android 多线程与异步通信机制(1)
android