SupervisorJob和supervisorScope的区别

SupervisorJob和supervisorScope的区别

SupervisorJob只能表示当前级别的错误拦截,其中子job还是不会被拦截

  val c =
           CoroutineExceptionHandler { coroutineContext: CoroutineContext, throwable: Throwable ->
                Log.e("123","${throwable.message}")
            }
 val sc = CoroutineScope(supervisorJob)
        sc.launch(c) {
            delay(1000)
            Log.e("123","task1")
            throw Throwable("baocuo")
        }
        sc.launch(c){
            delay(2000)
            Log.e("123","task2")
        }			
        结果:
        	//task1
        	//baocuo
        	//task2

可见sc层级的兄弟job都互不影响

但是如果代码如下

        sc.launch(c) {
            launch {
                delay(1000)
                Log.e("123","task1")
                throw Throwable("baocuo")
            }
            launch {
                delay(2000)
                Log.e("123","task2")
            }
        }
        结果:
        	//task1
        	//baocuo

task1报错,task2也被取消了

      sc.launch(c) {
            launch {
                delay(500)
                Log.e("123","task")
                throw Throwable("baocuo111")
            }
            delay(1000)
            Log.e("123","task1")
            throw Throwable("baocuo")
        }
        sc.launch(c){
            delay(2000)
            Log.e("123","task2")
        }
        结果:
	2023-10-25 00:13:17.404 16453-16496                 E  task
	2023-10-25 00:13:17.412 16453-16496                 E  baocuo111
	2023-10-25 00:13:18.898 16453-16496                 E  task2

结果正确

 sc.launch(c) {
            supervisorScope {
                launch {
                    delay(1000)
                    Log.e("123","task1")
                    throw Throwable("baocuo")
                }
                launch {
                    delay(2000)
                    Log.e("123","task2")
                }
            }
        }

supervisorScope 表示下面的launch都是supervisorJob,所以task1和task2互不影响

supervisorJob只是对原job进行了一次包装,详情请看 kotlinx.coroutines.JobSupport里面childCancelled 和notifyCancelling的实现

在协程中,可以使用协程作用域中的 `cancel()` 函数来取消一个协程。当协程被取消时,它会抛出一个 `CancellationException` 异常。如果在协程中捕获了这个异常,那么协程的执行会立即结束。 然而,在某些情况下,我们可能不想让协程被取消,或者不想让它在取消时抛出异常。这时候我们就可以使用 `SupervisorJob` 和 `SupervisorScope` 来管理协程的取消操作。 `SupervisorJob` 是一个特殊的 `Job` 类型,它会将所有子协程放入一个单独的协程作用域中,从而使它们互相独立。当一个子协程被取消时,其它子协程不会受到影响。同时,如果使用 `SupervisorScope` 来启动子协程,则在取消时也不会抛出 `CancellationException` 异常。 下面是一个例子,展示了如何在协程中使用 `SupervisorJob` 和 `SupervisorScope`: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { val supervisor = SupervisorJob() val scope = CoroutineScope(coroutineContext + supervisor) val job1 = scope.launch { println("Child coroutine 1 started") delay(1000) println("Child coroutine 1 completed") } val job2 = scope.launch { println("Child coroutine 2 started") try { delay(3000) println("Child coroutine 2 completed") } catch (e: CancellationException) { // do nothing } } delay(2000) job1.cancel() job2.cancel() supervisor.children.forEach { it.join() } println("All coroutines completed") } ``` 在这个例子中,我们首先创建了一个 `SupervisorJob`,然后使用它来创建一个协程作用域。在协程作用域中,我们创建了两个子协程 `job1` 和 `job2`。在 `job1` 中,我们没有使用 `SupervisorScope`,所以在取消时会抛出 `CancellationException` 异常。而在 `job2` 中,我们使用了 `SupervisorScope`,所以在取消时不会抛出异常。 最后,我们通过遍历 `supervisor.children` 来等待所有子协程执行完毕,并输出 "All coroutines completed"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值