香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 99|回复: 0

Android-协程的异常处理

[复制链接]

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2022-9-23 08:50:28 | 显示全部楼层 |阅读模式
一、协程的上下文

CoroutineContext是一组用于定义协程行为的元素。它由如下几项构成:
1)Job:控制协程的生命周期;
2)CoroutineDispatcher:向合适的线程分发任务;
3)CoroutineName:协程的名称,调试的时候很有用;
4)CoroutineExceptionHandler:处理未被捕捉的异常;
二、组合上下文中的元素

有时我们需要在协程上下文中定义多个元素。我们可以使用+操作符来实现。比如说,我
们可以显式指定一个调度器来启动协程并且同时显式指定一个命名:
1、组合协程的名称
在 Android 中调试时候打印名称,需要下面的方式开启 debug。
// 协程名称,需要再 Application 中开启,才可以看到,调试模式下可见
// https://www.5axxw.com/questions/content/ixlwc4
System.setProperty("kotlinx.coroutines.debug", "on" )
    /**
     * 协程上下文组合
     */
    @Test
    fun `test CoroutineContext`() = runBlocking<Unit> {
        launch(Dispatchers.Default + CoroutineName("young_test_coroutine")) {
            println("run on thread ${Thread.currentThread().name}")
        }
    }

执行结果:
run on thread DefaultDispatcher-worker-1 @young_test_coroutine#2三、协程上下文的继承

对于新创建的协程,它的CoroutineContext会包含一个全新的Job实例,它会帮助我们
控制协程的生命周期。而剩下的元素会从CoroutineContext的父类继承,该父类可能是
另外一个协程或者创建该协程的CoroutineScope。
    /**
     * 协程上下文的继承
     */
    @Test
    fun `test CoroutineContext extend`() = runBlocking<Unit> {
        val scope = CoroutineScope(Dispatchers.IO + CoroutineName("young_test_coroutine"))

        val job = scope.launch {
            println("${coroutineContext[Job]} ${Thread.currentThread().name}")
            val result =async {
                println("${coroutineContext[Job]} ${Thread.currentThread().name}")
                "返回结果"
            }.await()
        }

        job.join()

    }

执行结果:
"young_test_coroutine#2":StandaloneCoroutine{Active}@542546f5 DefaultDispatcher-worker-1 @young_test_coroutine#2
"young_test_coroutine#3":DeferredCoroutine{Active}@746a6335 DefaultDispatcher-worker-3 @young_test_coroutine#3四、协程上下文的继承公式

协程的上下文=默认值+r继承的CoroutineContext +参数
1)一些元素包含默认值:Dispatchers.Default是默认的CoroutineDispatcher,以及“coroutine作为默认的CoroutineName;
2)继承的CoroutineContext是CoroutineScope或者其父协程的CoroutineContext;
3)传入协程构建器的参数的优先级高于继承的上下文参数,因此会覆盖对应的参数值。

下面的例子,最终的父级CoroutineContext会内含Dispatchers.lO而不是scope对象里的Dispatchers.Main
因为它被协程的构建器里的参数覆盖了。此外,注意一下父级CoroutineContext里的Job是scope对象的Job(红色),而新的Job实例(绿色)会赋值给新的协程的CoroutineContext。


    /**
     * 协程上下文拼接(理解上下文继承)
     */
    @Test
    fun `test CoroutineContext extend2`() = runBlocking<Unit> {
//        val coroutineExceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
//            println("caught ${throwable.message}")
//        }
        // 不需要使用的参数,可以用 _ 代替,可以节省一点内存
        val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
            println("caught ${throwable.message}")
        }

        val scope = CoroutineScope(Job() + Dispatchers.Main + coroutineExceptionHandler)

        val job = scope.launch(Dispatchers.IO) {
            // 新的协程
            
        }
    }五、协程异常处理

1、异常处理的必要性
当应用出现一些意外情况时,给用户提供合适的体验非常重要,一方面,目睹应
用崩溃是个很糟糕的体验,另一方面,在用户操作失败时,也必须要能给出正确
的提示信息。
2、异常的传播(根协程)
协程构建器有两种形式:自动传播异常(launch与actor),向用户暴露异常
(async与produce)当这些构建器用于创建一个根协程时(该协程不是另一个协程的子协程),前者这类构建器,异常会在它发生的第一时间被抛出,而后者则依赖用户来最终消费异常,例如通过await或receive。
2.1 异常的位置(根协程的情况)
    /**
     * 异常传播
     */
    @Test
    fun `test Exception Propagation`() = runBlocking<Unit> {
        val job = GlobalScope.launch {
            // 异常发生在这个位置
            throw IndexOutOfBoundsException()
        }
        job.join()

        val deferred = GlobalScope.async {
            throw ArithmeticException()
        }
        // 异常发生在这个位置
        deferred.await()
    }

执行结果:
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IndexOutOfBoundsException
        at com.young.testcoroutine.CoroutineTest07$test Exception Propagation$1$job$1.invokeSuspend(CoroutineTest07.kt:73)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

java.lang.ArithmeticException
        at com.young.testcoroutine.CoroutineTest07$test Exception Propagation$1$deferred$1.invokeSuspend(CoroutineTest07.kt:78)
        (Coroutine boundary)
        at kotlinx.coroutines.DeferredCoroutine.await$suspendImpl(Builders.common.kt:101)
        at com.young.testcoroutine.CoroutineTest07$test Exception Propagation$1.invokeSuspend(CoroutineTest07.kt:81)
Caused by: java.lang.ArithmeticException
        at com.young.testcoroutine.CoroutineTest07$test Exception Propagation$1$deferred$1.invokeSuspend(CoroutineTest07.kt:78)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)




方便看上面的异常的行号

2.1 异常传播,catch 异常(根协程的情况)
    /**
     * 异常传播,catch 异常
     */
    @Test
    fun `test Exception Propagation1`() = runBlocking<Unit> {
        val job = GlobalScope.launch {
            // 异常发生在这个位置
            try {
                throw IndexOutOfBoundsException()
            } catch (e: Exception) {
                println("catch IndexOutOfBoundsException ${e.message}")
            }
        }
        job.join()

        val deferred = GlobalScope.async {
            throw ArithmeticException()
        }
        // 异常发生在这个位置
        try {
            deferred.await()
        }catch (e:Exception){
           println("catch ArithmeticException ${e.message}")
        }
    }

执行结果:
catch IndexOutOfBoundsException null
catch ArithmeticException null
    /**
     * 异常传播,catch 异常
     */
    @Test
    fun `test Exception Propagation1`() = runBlocking<Unit> {
        val job = GlobalScope.launch {
            // 异常发生在这个位置
            try {
                throw IndexOutOfBoundsException()
            } catch (e: Exception) {
                println("catch IndexOutOfBoundsException ${e.message}")
            }
        }
        job.join()

        val deferred = GlobalScope.async {
            throw ArithmeticException()
        }
        // 异常发生在这个位置
        // 依赖用户来最终消费异常,例如通过await或receive
        // 如果将  deferred.await() 注释,就不会有 ArithmeticException
        try {
            deferred.await()
        }catch (e:Exception){
           println("catch ArithmeticException ${e.message}")
        }
    }
执行结果:
catch IndexOutOfBoundsException null3、非根协程的异常
其他协程(非根协程)所创建的协程中,产生的异常总是会被传播。
3.1 异常抛出
当前例子抛的顺序:async -> launch
    /**
     * 非根协程的异常传播
     *
     * 非根协程,不需要调用 await 等,有异常直接就抛出
     *
     */
    @Test
    fun `test exception propagation2`() = runBlocking {
        val scope = CoroutineScope(Job())
        val job = scope.launch {
            async {
                // 如果async抛出异常,launch就会立即抛出异常,而不会调用.await ()
                throw IllegalArgumentException()
            }
        }
        // 这里是把新协程加入到当前协程中进行等待
        job.join()
    }

执行结果:
Exception in thread "DefaultDispatcher-worker-1 @coroutine#3" java.lang.IllegalArgumentException
        at com.young.testcoroutine.CoroutineTest07$test exception propagation2$1$job$1$1.invokeSuspend(CoroutineTest07.kt:125)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)


方便对照行号

六、异常的传播特性(非根协程)

1、当一个协程由于一个异常而运行失败时,它会传播这个异常并传递给它的父级。接下来,父级会进行下面几步操作:
1)取消它自己的子级;
2)取消它自己;
3)将异常传播并传递给它的父级。



非根协程异常传播图示

2、如果按照 1 的传播特性,那做业务开发就比较多坑,那我们是否可以处理哪个异常只关闭哪个呢?当然有,那就是 SupervisorJob
3、SupervisorJob
1)使用SupervisorJob时,一个子协程的运行失败不会影响到其他子协程SupervisorJob不会传播异常给它的父级,它会让子协程自己处理异常;
2)这种需求常见于在作用域内定义作业的UI组件,如果任何一个Ul的子作业执行失败了,它并不总是有必要取消整个UI组件,但是如果UI组件被销毁了,由于它的结果不再被需要了,它就有必要使所有的子作业执行失败。
3.1 验证 SupervisorJob 出现异常不影响其他子协程的功能(job2 一直在打印)
/**
     * 测试 SupervisorJob
     */
    @Test
    fun `test SupervisorJob`() = runBlocking<Unit> {
        val scope = CoroutineScope(SupervisorJob())

        val job = scope.launch {
            delay(100)
            println("协程 1")
            throw IllegalArgumentException()
        }

        val job2 = scope.launch {
            try {
                while (isActive) {
                    delay(1000)
                    println("协程 2 ${System.currentTimeMillis()}")
                }
            } finally {
                println("协程2 finally")
            }
        }

        joinAll(job, job2)

    }

执行结果:
协程 1
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IllegalArgumentException
        at com.young.testcoroutine.CoroutineTest07$test super$1$job$1.invokeSuspend(CoroutineTest07.kt:142)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
协程 2 1663163589339
协程 2 1663163590353
协程 2 1663163591369
协程 2 1663163592369
...3.2 使用 Job 执行 3.1 的代码
    /**
     * 使用 job 执行,发现其他子协程也关闭了
     */
    @Test
    fun `test super`() = runBlocking<Unit> {
        val scope = CoroutineScope(Job())

        val job = scope.launch {
            delay(100)
            println("协程 1")
            throw IllegalArgumentException()
        }

        val job2 = scope.launch {
            try {
                while (isActive) {
                    delay(1000)
                    println("协程 2 ${System.currentTimeMillis()}")
                }
            } finally {
                println("协程2 finally")
            }
        }

        joinAll(job, job2)

    }

执行结果:
协程 1
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IllegalArgumentException
        at com.young.testcoroutine.CoroutineTest07$test super$1$job$1.invokeSuspend(CoroutineTest07.kt:170)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
协程2 finally3.3 测试 SupervisorJob 取消,取消了,全部子协程和本身都取消了
    /**
     * 测试 SupervisorJob 取消,取消了,全部子协程和本身都取消了
     */
    @Test
    fun `test SupervisorJob Cancel`() = runBlocking<Unit> {
        val scope = CoroutineScope(SupervisorJob())

        val job = scope.launch {
            delay(100)
            println("协程 1")
            throw IllegalArgumentException()
        }

        val job2 = scope.launch {
            try {
                while (isActive) {
                    delay(1000)
                    println("协程 2 ${System.currentTimeMillis()}")
                }
            } finally {
                println("协程2 finally")
            }
        }

        delay(200)
        scope.cancel()

        joinAll(job, job2)

    }

执行结果:
协程 1
Exception in thread "DefaultDispatcher-worker-1 @coroutine#2" java.lang.IllegalArgumentException
        at com.young.testcoroutine.CoroutineTest07$test SupervisorJob Cancel$1$job$1.invokeSuspend(CoroutineTest07.kt:198)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
协程2 finally3.4 supervisorScope (作用跟 SupervisorJob 差不多)
当作业自身执行失败的时候,所有子作业将会被全部取消。
3.4.1 测试 supervisorScope 的使用,效果跟 SupervisorJob 一样
    /**
     * 测试 supervisorScope 的使用,效果跟 SupervisorJob 一样
     */
    @Test
    fun `test supervisorScope`() = runBlocking<Unit> {
        supervisorScope {
            launch {
                delay(100)
                println("协程 1")
                throw IllegalArgumentException()
            }


            try {
                while (true){
                    delay(1000)
                    println("协程2 ${System.currentTimeMillis()}")
                }
            } finally {
                println("supervisorScope 被干掉了")
            }
        }
    }

执行结果:
协程 1
Exception in thread "Test worker @coroutine#2" java.lang.IllegalArgumentException
        at com.young.testcoroutine.CoroutineTest07$test supervisorScope$1$1$1.invokeSuspend(CoroutineTest07.kt:229)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:227)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:362)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:396)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:388)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:484)
        at kotlinx.coroutines.EventLoopImplBase$DelayedResumeTask.run(EventLoop.common.kt:489)
        at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
        at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
        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.young.testcoroutine.CoroutineTest07.test supervisorScope(CoroutineTest07.kt:224)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
        at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
        at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
协程2 1663164932759
协程2 1663164933763
协程2 1663164934779
协程2 1663164935780
....3.4.2 测试 supervisorScope 的使用,让自己抛出异常,子协程也会被取消
    /**
     * 测试 supervisorScope 的使用,让自己抛出异常,子协程也会被取消
     */
    @Test
    fun `test supervisorScope2`() = runBlocking<Unit> {
        supervisorScope {
            val child = launch {
                try {
                    delay(Long.MAX_VALUE)
                    println("协程2 ${System.currentTimeMillis()}")
                } finally {
                    println("child 被干掉了")
                }
            }

            yield()
            println("supervisorScope 准备抛出异常")
            throw AssertionError()

        }
    }

执行结果:
supervisorScope 准备抛出异常
child 被干掉了

java.lang.AssertionError
        at com.young.testcoroutine.CoroutineTest07$test supervisorScope2$1$1.invokeSuspend(CoroutineTest07.kt:262)
        (Coroutine boundary)
        at com.young.testcoroutine.CoroutineTest07$test supervisorScope2$1.invokeSuspend(CoroutineTest07.kt:250)
Caused by: java.lang.AssertionError
        at com.young.testcoroutine.CoroutineTest07$test supervisorScope2$1$1.invokeSuspend(CoroutineTest07.kt:262)
        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:274)
        at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
        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.young.testcoroutine.CoroutineTest07.test supervisorScope2(CoroutineTest07.kt:249)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
        at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
        at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
        at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
        at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
        at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
        at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
        at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-3-15 04:55 , Processed in 1.009688 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表