关于kotlin coroutine的一些个人理解

697 阅读2分钟

这里写的都是一些对协程的个人理解,如有问题,还望多多指教

kotlin中有多种方式可以用于创建协程,其中,最常用的就是launch和async

launch就不多说了,最简单的用于创建协程的方式,而async这个方法,我的理解是:

1.async并没有做延迟操作,需要延迟操作的,构建协程时应该将start参数传 CoroutineStart.LAZY

2.async也不是用来做并发操作的,只要在协程作用域中,不管是launch还是async,只要开启一个协程,就会开始工作

3.async在SupervisorJob或supervisorScope中,产生的异常并不会传递到父级,async作为最外层的协程开启方式时,异常会被静默的抛弃,只有在调用await()方法获取结果时才会抛出异常,而作为其他协程的内部协程时,会将异常传递到父级,此时并不需要调用await()方法

对于supervisorScope和SupervisorJob的理解:

1.创建方式或者说工作方式有两种:

在协程中,使用supervisorScope,类似于下面这样:

    // Scope 控制我的应用中某一层级的协程
val scope = CoroutineScope(Job())
 
 
scope.launch {
    supervisorScope {
        launch {
            // Child 1
        }
        launch {
            // Child 2
        }
    }
}

或者直接使用CoroutineScope(SupervisorJob()) 创建,类似下面这样:

class Test : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.IO + CoroutineExceptionHandler { coroutineContext, throwable ->  }) {

    private  val TAG = "Test"

    fun test(){//这里的两个协程,其中一个出错,另一个还会继续运行
        launch(start = CoroutineStart.LAZY) { throw Exception("aaa") }
        launch { Log.i(TAG, "test: ${Thread.currentThread().name}, ${coroutineContext[Job]}")
            for (i in 0..100){
                delay(1000)
                Log.i(TAG, "doSomething: $i")
            }
        }
    }
}

除了这两种,其他的不管launch还是async,创建的都是普通的Job

2.使用supervisorScope或SupervisorJob后,产生的异常还是会传递到父级,只是说不会影响到父级的其他子协程的工作

3.其实只要对子launcher做了异常处理,不让异常传递到父级,同样不会对父级中的其他子协程产生影响

### 对于CoroutineExceptionHandler的理解:

1.CoroutineExceptionHandler 是 CoroutineContext 的一个可选元素,它让您可以处理未捕获的异常。 只要在父级配置了CoroutineExceptionHandler,子协程中产生的异常,都会被父级的CoroutineExceptionHandler所捕获,类似于这样:

val scope = CoroutineScope(Job())
scope.launch(handler) {
   launch {
       throw Exception("Failed coroutine")
   }
}

2.子launcher如果想要自己处理异常而不进行传递,可以在子协程中使用try catch包裹,而不是在子协程中配置CoroutineExceptionHandler


val scope = CoroutineScope(Job())
scope.launch {
   launch(handler) {
       throw Exception("Failed coroutine")
   }
}

异常不会被捕获的原因是因为 handler 没有被安装给正确的 CoroutineContext。内部协程会在异常出现时传播异常并传递给它的父级,由于父级并不知道 handler 的存在,异常就没有被抛出。

参考链接:

blog.csdn.net/jILRvRTrc/a…