这里写的都是一些对协程的个人理解,如有问题,还望多多指教
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 的存在,异常就没有被抛出。
参考链接: