Featured image of post 协程中的线程

协程中的线程

在上一节介绍过Dispatchers.IO,它是一个CoroutineDispatcher对象,CoroutineDispatcher的执行是在DispatchedContinuation中的resumeCancellableWith方法,如果CoroutineDispatcher的isDispatchNeeded返回true,则会执行CoroutineDispatcher的dispatch方法。否则直接执行该runnable。

Dispatchers.Main

在安卓平台下,它其实是一个HandlerContext对象: HandlerContext创建 看下它的isDispatchNeeded和dispatch方法: HandlerContext的两个方法 此时invokeImmediately默认是false,因此isDispatchNeeded返回true。所以会执行它的dispatch方法。在dispatch方法中将runnable给到了主线程的消息队列中,然后等主线程从消息队列中取该runnable。所以在上一节例子中它是晚于onCreate方法执行的。

Dispatchers.Main.immediate

它是HandlerContext中的immediate变量: HandlerContext中的immediate创建 可以看到它是新创建了一个HandlerContext,并且invokeImmediately是true。在上一节的例子中,它的isDispatchNeeded返回false。所以它是直接执行SuspendLambda的resumeWith方法,因此上一节例子中它是要早于Dispatchs.Main执行的。

Dispatchers.IO

看下它的CoroutineDispatcher,对应的子类是DefaultIoScheduler,CoroutineDispatcher的isDispatchNeeded方法默认返回true,所以会执行它的dispatch方法: DefaultIoScheduler 在dispatch方法中调用了default的dispatch方法,default实际是一个LimitedDispatcher方法,看下它的dispatch方法: LimitedDispatcher 在上面2处,判断当前runningWokers的数量,如果大于parallelism的时候,则不创建Worker,此处的parallelism的大小是64。从此处也能看出来Dispatchers.IO的线程数量不会超过64个。 最终该方法里面会通过DefaultScheduler.dispatchWithContext来创建CoroutineScheduler,来看下创建线程池的几个参数: 创建线程池的参数 核心线程数: 核心线程数 最小2个,最大是cpu的核数 最大线程数: 最大线程数 最大线程数取值(1 shl BLOCKING_SHIFT) - 2:最终得到的值是2^21-2 = 2097150。 非核心线程空闲时间是60s。

结论:Dispatchers.IO创建的最大的线程个数为:Math.max(64,cpu核数)

Dispatchers.Default

它是由DefaultScheduler构建的线程池,它所创建的最大的线程个数为:Math.max(2,cpu核数)

Dispatchers.IO和Dispatchers.Default都是由DefaultScheduler构建的,而DefaultScheduler其实是一个单例,因此不难看出它两是共用一个线程池的,只不过当Dispatchers.IO时候,最大线程个数控制在Math.min(64,cpu核数),最多不会超过64个,Dispatchers.Default控制在cpu核数个数上。Dispatchers.Default常用作cpu密集型的任务,比如图片模糊处理、繁杂的计算型可以用这种类型的线程池。Dispatchers.IO由于它的线程数量多,并且它不能消耗cpu资源,因此常用作io处理,文件读写等操作上。 关于这点,可以看这篇文章:dispatcher拆解

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy