KotlinDispatchers协程调度器源码深入分析 |
||||||||||||||
+ 目录
Dispatchers协程调度器CoroutineDispatcher,具有用于调度任务的底层执行器。ExecutorCoroutineDispatcher的实例应由调度程序的所有者关闭。 此类通常用作基于协程的API和异步API之间的桥梁,异步API需要Executor的实例。 根据各种调度器的继承关系,梳理如下继承结构:
CoroutineDispatcher基类将由所有协程调度器实现扩展,kotlin官方实现了以下四种调度器: Dispatchers.Default -如果上下文中未指定调度器或任何其他ContinuationInterceptor,则所有标准构建器都使用默认值。它使用共享后台线程的公共池。对于消耗CPU资源的计算密集型协程来说,这是一个合适的选择。 Dispatchers.IO -使用按需创建线程的共享池,用于卸载IO密集型阻塞操作(如文件I/O和阻塞套接字I/O)。 Dispatchers.Unconfined -在当前调用帧中启动协程执行,直到第一次暂停,然后协程生成器函数返回。协程稍后将在相应的挂起函数使用的任何线程中恢复,而不将其限制在任何特定的线程或池中。无约束调度器通常不应在代码中使用。 HandlerContext -在主线程中调度任务,android中主线程也就是ui线程,使用该调度器谨慎ANR异常,不应该使用该调度器调度阻塞或者耗时任务。 可以使用newSingleThreadContext和newFixedThreadPoolContext创建专用线程池。 可以使用asCoroutineDispatcher扩展函数将任意执行器转换为调度器。
Dispatchers.Default 这个调度器的类型是DefaultScheduler,一般是做cpu密集计算型任务,内部包含的成员变量IO,也就是对应的Dispatchers.IO调度器。主要实现在
?
Default调度器其实没做什么特别的操作,只是用coroutineScheduler代理实现了协程的调度。
Dispatchers.IO这个是LimitingDispatcher类型的,是DefaultScheduler类型的成员变量,而LimitingDispatcher类型又是继承自ExecutorCoroutineDispatcher的,LimitingDispatcher在它基础上做了有调度个数限制的排队机制,IO这个名字代表的IO操作,IO操作又是阻塞线程的操作,线程不能及时释放,所以加入了队列机制,防止IO线程爆炸式增长。如下:
?
构造函数 传入了parallelism参数 ,这个是并发数。 dispatchYield方法 实现是直接调用的dispatch方法。 dispatch方法:一个while循环,循环内,
?
afterTask方法 这个方法是任务调度结束后的回调,这里面首先从队列中取出一个任务, 任务不为空,让调度器调度这个任务,结束; 为空,给调度任务数加一,然后尝试取出任务,为空返回,不为空,继续调用dispatch方法,整个流程就串起来了。 整个流程如下图所示:
综上:IO调度器侧重于调度任务数量的限制,防止IO操作阻塞线程,让线程数量爆炸式增长。
Dispatchers.Main 具体的实现类是
?
主线程中调度任务,android中主线程也就是ui线程。实现原理是内部持有一个 在调用dispatch调度方法的时候,是使用handler发送一个Runnable任务,
?
在delay的时候,如果当前的dispatcher正是HandlerContext,那么实现是handler发送一个延迟了
?
下面这个方法也比较常看到,就是协程在调度continuation的时候,会去判断是不是需要去调度,不需要的话,直接在当前线程执行,需要调度的,需要由dispatcher来重新调度任务,这样可能执行的线程会被切换,如果不是主线程的话,、就需要调度了, 如果是主线程的话立刻执行。
?
|