作用:核心的作用就是用来简化异步执行的代码,避免了线程间的切换、调度、数据传递导致的性能、资源浪费,本质上是一种轻量级的线程。
解决的问题:
(1)处理耗时任务,这种任务常常会阻塞住主线程。
(2)保证主线程安全,即确保安全地从主线程调用任何 suspend 函数
特点:
轻量级的线程、开销小无成本、数量几乎没有限制
容易控制生命周期
用同步的方式去表达异步,杜绝回调地狱.
依赖于当前线程,线程结束,协程也会结束
运行在单线程中的并发处理
主要使用方法
协程的挂起和恢复:
suspend --称为挂起或者暂停,用于暂时执行当前协程,并保存所有局部变量。
resume -用于让已暂停的协程从暂停处继续执行。
我理解的挂起是,比如在主线程运行挂起函数,这个时候会记录下该挂起函数,但是不影响主线线程其他函数执行,等待挂起函数执行完成后,会再次恢复到主线程继续执行。挂起实现既可以不阻塞线程也可以直接获取异步或者耗时操作数据获得。
使用suspend 修饰的函数叫挂起函数,挂起函数只在协程体内或者其他挂起函数内使用。
协程挂起的实质:就是切个线程
协程就是切线程
挂起就是可以自动切回来的切线程
非阻塞式是用看起来阻塞的代码实现非阻塞的操作
suspend(协程的核心)
被suspend标记的函数称为可挂起函数,此类函数必须在协程中或者另外一个suspend标记的函数中调用,协程代码块中遇到suspend函数,会将该函数挂起执行,挂起函数执行完毕以后,继续执行剩余协程代码块中代码,这是协程实现异步的核心。
协程调度器
1. main 主线程
2. Io 对磁盘和网络Io做了优化,包括数据库,文件读写,网络处理。
]3. Default cpu密集型任务进行了优化,包括数组排序,json解析,处理差异判断
协程的启动模式
1.Defaul:协程创建后立即开始调度,在调度前协程如果被取消了,就直接进入取消响应状态。
2.Atomic:协程创建后立即开始调度,协程执行到第一个挂起点之前不相应取消
3.Lazy: 只有协程被需要时,包括主动调用start join或者await等函数时才会开始调度,如果调度前就被取消,那么该协程将直接进入异常结束状态
4.Undispatched:协程创建后立即在当前函数调(注:在创建的协程的线程里执行)用栈种执行,直到遇到第一个正真挂起点。用到需要立即开始执行的需要这个方式。
协程的作用域构建器
coroutineScope:是挂起函数,不阻塞当前线程,作用域内一个协程失败了,所有其他剩余协程都会被取消。
supervisorScope :是挂起函数,不阻塞当前线程,作用域内一个协程失败了,不会影响其他剩余协程。
Job对象
1.对于每个创建的协程都会返回一个job实例,该实例是协程的唯一标示,并且负责管理协程的生命周期。
2.job的生命周期包括 创建(new) 活跃(Active) 完成中 (completing)。已完成(completed) 取消中(canceling)和已取消(cancelled),虽然直接拿不到job的这些状态,但是可以空过is方法可以进行判断。
协程的取消
1. 取消作用域会取消它的子协程
2. 被取消的子协程不会影响其他兄弟协程
3. 协程通常会抛出特殊异常来处理取消操作
4. 所有kotinx.coroutines中的挂起函数(withContext delay)都是可以取消的。
Cup密集型任务取消
1. 使用isActiv 如果job不是活跃状态则不执行任务
2. 使用在运算代码前添加ensureActive()来抛出异常终止运算。
3. 使用在运算代码前添加Yield()来抛出异常来出让执行权给其他协程,达到暂时协程取消的目的。从而保障其他线程的正常运行。