协程简单上手(线程切换)

上一篇文章中我们分析了挂起函数的本质(状态机),以及查看编译器为我们生成的类里面是如何借用状态机实现的"挂起",那么在实际coding中我们该如何使用协程呢?

协程作用域

所有协程都必须在一个协程作用域CoroutineScope内运行。一个 CoroutineScope 管理一个或多个相关的协程。

协程如何开启呢?可以通过launch和async函数创建协程并将其函数主体的执行分派给相应的调度程序

调度程序也就是launch和async的函数主体会运行在哪个线程中。比如

javascript 复制代码
launch(Dispatchers.IO){
     //协程主体函数
}

Dispatchers.IO 指示此协程应在为 I/O 操作预留的线程上执行。

那么当协程内部还需要切换线程的时候呢?典型的场景比如开启协程获取数据需要进行不同的线程切换: 这时候可以使用withContext

javascript 复制代码
withContext(Dispatchers.IO) {
            // IO线程运行
        }

当withContext运行完成之后会自动恢复调用withContext的线程中。

如何看阻塞

同一协程体内的代码是阻塞的,但是协程体里面又开启了一个协程,两个协程不影响各自运行,但父协程取消的时候默认子协程也会取消。

取消协程运行

不管是通过launch还是async开启的协程,其都会返回一个Job对象,调用该Job对象的cancel即可取消协程。协程内部会通过抛出一个取消异常终止运行。

上面是针对某一个具体的协程取消,如果我想全部取消呢?比如界面销毁的时候,通过调用协程域的取消,位于这个协程域里面的协程都会取消。 Android为我们自动提供了一个viewmodelScope,他可以在配置改变引起的销毁重建时自动取消开启协程不用担心泄漏问题。

CoroutineContext

CoroutineContext 使用以下元素集定义协程的行为:代表该协程的上下文信息比如协程的名称,协程的调度器(Dispatcher),异常处理等

  • Job:控制协程的生命周期。
  • CoroutineDispatcher:将工作分派到适当的线程。
  • CoroutineName:协程的名称,可用于调试。
  • CoroutineExceptionHandler:处理未捕获的异常。

协程如何测试

开启协程

runTest 是用于测试的协程构建器。相比于正式编码的时候使用的是launch和async。使用此构建器可封装包含协程的任何测试。

必须使用指定调度器

通过TestDispatchers调度器来指定协程的运行线程,相比于正式编码使用的是Dispatchers.IO,Dispatchers.Main,Dispatchers.Default。 除 runTest 创建的顶级协程外,如果代码还创建了新的协程,则需要选择适当的 TestDispatcher,以控制这些新协程的调度方式,设置新协程的调度器。 TestDispatchers是用于测试的 [CoroutineDispatcher] 实现。由于多线程下的测试是不可预测的,所以正式编码中出现的withContext切换线程应换成单线程的方式因为这样将会使得结果可预测,所以再项目中不能使用硬编码去设置调度器Dispatchers,应该使用注入的方式如果是测试注入TESTDispatchers,如果是正式注入正常的Dispatcher。

相关推荐
m0_493934539 小时前
如何监控AWR数据收集Job_DBA_SCHEDULER_JOBS中的BSLN_MAINTAIN_STATS
jvm·数据库·python
a95114164210 小时前
Go语言如何操作OSS_Go语言阿里云OSS上传教程【完整】
jvm·数据库·python
2401_8971905510 小时前
MySQL中如何利用LIMIT配合函数分页_MySQL分页查询优化
jvm·数据库·python
Polar__Star10 小时前
C#怎么使用并发集合 C#ConcurrentDictionary和ConcurrentQueue线程安全集合怎么用【进阶】
jvm·数据库·python
m0_4939345311 小时前
Go语言中 & 与 - 的本质区别及指针使用详解
jvm·数据库·python
Greyson111 小时前
Redis如何解决哨兵通知延迟问题_优化客户端连接池动态刷新拓扑的订阅监听机制
jvm·数据库·python
weixin_5806140012 小时前
如何防止SQL注入利用存储过程_确保存储过程不拼字符串.txt
jvm·数据库·python
weixin_4087177712 小时前
mysql权限表查询性能如何优化_MySQL系统权限缓存原理
jvm·数据库·python
吕源林12 小时前
怎么优化MongoDB的软删除设计_布尔标记与删除时间戳
jvm·数据库·python
想唱rap12 小时前
C++智能指针
linux·jvm·数据结构·c++·mysql·ubuntu·bash