我学习协程的历程
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 挂起被恢复后也被执行了
到了这里协程中比较常用协同作用域就介绍完了,但是这里面案例还是有一些问题,那就是异常的处理,关于异常的相关介绍,在后续的文章中会介绍到