欢迎光临散文网 会员登陆 & 注册

Coroutine 学习(一)挂起,CoroutineScope,异常

2021-09-27 21:03 作者:房顶上的铝皮水塔  | 我要投稿


理解挂起

在我个人的理解中,挂起、挂起函数指的是当前的函数可以被「搁置」,不影响主流程的运行

在以上的代码中,launch中的函数会立刻执行,但是需要等待5s。由于挂起函数有不影响主流程的特性,所以会先输出hello world,等到5s后再打印the job is done。

但是在这里的代码中,由于join函数会先挂起当前的协程,等到job执行完成。当前的协程是什么? 当然是由runBlocking引导的协程,所以会先打印the job is done.

CoroutineContext

协程总是运行在一些以CoroutineContext类型为代表的上下文中。协程上下文在类型上更接近一个List。CoroutineContext包含一个调度器



CoroutineScope

CoroutineScope会跟踪它使用的launch和aysnc创建的所有协程。ViewModel有viewModelScope,LifeCycle有lifecycleScope。每一个协程构建器都是CoroutineScope的扩展函数,并且继承了其中的CoroutineContext。所以当使用CoroutineContext的协程构建器创建新的协程时,会继承CoroutineContext中的信息

Job表示协程的句柄,可以通过这个类的实例来管理协程的生命周期


协程的异常处理

launch和async的对于异常的处理机制不同。当使用这两种构建器创建根协程时,launch会将异常视作未捕获异常,async需要对异常手动处理:

这里的打印行为是通过CoroutineExceptionHandler处理的。可以自定定义CoroutineExceptionHandler:

取消与异常:

在下面的代码中,父协程创建的实例是job,子协程创建的实例是child。使用的是Global.launch中调度的子协程,所以父子协程都具有相同的CoroutineContext。yield表示让出当前的协程调度器,给使用者同一个协程调度器的另外一个协程使用,这个协程就是child。但是很明显,这个让给子协程的动作好像只做了一下,如果是Dispatcher一直在子协程手中,则父协程不能有机会打印后面的内容。


job取消主动会抛出异常CancellationException,这个异常会被异常handler处理,但是不会结束父协程,所以打印的结果是:

子协程的取消不会影响父协程的取消,但是如果子协程遇到了CancellationException之外的异常,异常会被ExceptionHandler处理,父协程也随之结束:

输出:


下面的代码展示了多个子协程的情况,如果有其中一个子协程抛出异常,父协程也会结束,其他的子协程也被迫关闭:

多个子协程出现的异常只会捕捉第一个。


如果取消父协程,子协程也会被取消吗?

所以总结一下父子协程的关系:

覆巢之下无完卵: 父协程取消 子协程也取消 而且是都要取消

子不孝 父之过: 子协程取消 父协程也要取消


所以是一种双向关系


SupervisorJob实现单向关系

firstChild被取消了,但是并不会让secondChild停止,同时父协程也没有被停止。


我们可以使用supervisorScope实现类似的事情:

  1. 类似于SupervisoJob的单项传播

  2. 向coroutineScope一样,等到所有子协程结束之后结束自身

输出:

总结:

  1. 协程构建器中都有一个默认的CoroutineContext (协程上下文)

  2. 协程上下文就像List一样,我们可以往里面添加Dispatcher Job CoroutineExceptionHandler 等等

  3. 所有的协程构建器都是CoroutineScope的扩展函数,而CoroutineContext则是它的一个属性。CoroutineScope指定协程构建器,同时将自身的CoroutineContext用来配置构建器的【上下文信息】(dispatcher exceptionhandler....)

  4. 子协程表示继承了父协程CoroutineScope的协程。普通的CoroutineScope(也是普通的CoroutineContext)中,异常传递是双向的。但是这种双向传递关系可以被打破,通过在CoroutineContext中设置SupervisorJob或者直接通过supervisorScope构建协程。


Coroutine 学习(一)挂起,CoroutineScope,异常的评论 (共 条)

分享到微博请遵守国家法律