Kotlin Coroutines 笔记(二)

协程虽然是微线程,但是并不会和某一个特定的线程绑定,它可以在A线程中执行,并经过某一个时刻的挂起(suspend),等下次调度到恢复执行的时候,很可能会在B线程中执行。

一. withContext

与 launch、async、runBlocking 类似 withContext 也属于 Coroutine builders。不过与他们不同的是,其他几个都是创建一个新的协程,而 withContext 不会创建新的协程。withContext 允许更改协程的执行线程,withContext 在使用时需要传递一个 CoroutineContext 。

执行结果:

withContext 可以有返回值,这一点类似 async。async 创建的协程通过 await() 方法将值返回。而 withContext 可以直接返回。

执行结果:

二. 共享线程池

在上述的例子中,withContext 使用了 CommonPool。CommonPool 继承了 CoroutineDispatcher,表示使用线程池来执行协程的任务。

CommonPool 有点类似于 RxJava 的 Schedulers.computation(),主要是用于CPU密集型的计算任务。

CommonPool 使用 pool 来执行 block。

如果 pool 为空,则调用 getOrCreatePoolSync() 方法来创建 pool。

此时,createPool() 方法是正在创建 pool 的方法。

首先,安全管理器不为空的话,使用 createPlainPool() 来创建 pool。否则,尝试创建一个 ForkJoinPool,不行的话还是使用 createPlainPool() 来创建 pool。

createPlainPool() 会使用 Executors.newFixedThreadPool() 来创建线程池。

CommonPool 的创建原理大致了解之后,通过源码发现 CoroutineContext 默认的 CoroutineDispatcher 就是 CommonPool。

常见的 CoroutineDispatcher 还可以通过 ThreadPoolDispatcher 的 newSingleThreadContext()、newFixedThreadPoolContext()来创建,以及Executor 的扩展函数 asCoroutineDispatcher() 来创建。

在 Android 中,还可以使用UI。它顾名思义,在 Android 主线程上调度执行。

三. 可取消的协程

Job、Deferred 对象都可以取消任务。

3.1 cancel()

使用 cancel() 方法:

执行结果:

true表示job已经被取消了,并没有打印"Hello World!"

3.2 cancelAndJoin()

使用 cancelAndJoin() 方法:

执行结果:

cancelAndJoin() 等价于使用了 cancel() 和 join()。

join() 方法用于等待已启动协程的完成,并且它不会传播其异常。 但是,崩溃的子协程也会取消其父协程,并带有相应的异常。

3.3 检查协程的取消标记

如果一个协程一直在执行计算,没有去检查取消标记,它就无法取消。即使调用了cancel() 或者 cancelAndJoin()。

上述代码仍然会打印100次。

如果使用 检查取消标记,则Job 或 Deferred 的任务可以被取消:

执行结果:

isActive 是 CoroutineScope 的属性:

总结:

本文介绍了三个部分:withContext的使用,CommonPool的创建以及如何取消协程。其中,还捎带介绍了 async 和 await 的使用。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180731G0HYIE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券