概述
看这篇文章,可以跳着看,遇到哪个方法不懂就跳到哪个方法去看,上下对照着理解。
常量
companion object {
// A symbol to mark workers that are not in parkedWorkersStack
@JvmField
val NOT_IN_STACK = Symbol("NOT_IN_STACK")
// Worker ctl states
private const val PARKED = -1 // 在parkedWorkersStack栈上
private const val CLAIMED = 0 // 初始状态
private const val TERMINATED = 1 // 终止状态
// Masks of control state
/**
* |------------------------------------|---------------------|----------------------|
* | cpu permit(22bit) | BLOCKING(21bit) | CREATED(21bit) |
* |------------------------------------|---------------------|----------------------|
*/
private const val BLOCKING_SHIFT = 21 // 2M threads max
private const val CREATED_MASK: Long = (1L shl BLOCKING_SHIFT) - 1
private const val BLOCKING_MASK: Long = CREATED_MASK shl BLOCKING_SHIFT
private const val CPU_PERMITS_SHIFT = BLOCKING_SHIFT * 2
private const val CPU_PERMITS_MASK = CREATED_MASK shl CPU_PERMITS_SHIFT
internal const val MIN_SUPPORTED_POOL_SIZE = 1 // we support 1 for test purposes, but it is not usually used
internal const val MAX_SUPPORTED_POOL_SIZE = (1 shl BLOCKING_SHIFT) - 2
// Masks of parkedWorkersStack
/**
* |------------------------------------|---------------------|
* | PARKED_VERSION(43bit) | PARKED_INDEX(21bit)|
* |------------------------------------|---------------------|
*/
private const val PARKED_INDEX_MASK = CREATED_MASK
private const val PARKED_VERSION_MASK = CREATED_MASK.inv()
private const val PARKED_VERSION_INC = 1L shl BLOCKING_SHIFT
}
理论上最大支持2M的线程数量
CoroutineScheduler
CoroutineScheduler
实现了java的Executor
接口,是Dispatchers.Default
的调度器,它的调度逻辑就是,IO任务到IO线程中执行,CPU密集任务CPU型线程中去执行,对于调度的任务来说,什么io线程,什么cpu型线程,都是透明的,对任务来说都是线程。
线程池里面的线程名字叫做 DefaultDispatcher-worker-1,DefaultDispatcher-worker-2,DefaultDispatcher-worker-3
等之类的。
public actual object Dispatchers {
@JvmStatic
public actual val Default: CoroutineDispatcher = DefaultScheduler
}
internal val DEFAULT_SCHEDULER_NAME = systemProp(
"kotlinx.coroutines.scheduler.default.name", "DefaultDispatcher"
)
internal object DefaultScheduler : SchedulerCoroutineDispatcher(
CORE_POOL_SIZE, MAX_POOL_SIZE,
// DEFAULT_SCHEDULER_NAME的值默认就是 "DefaultDispatcher"
IDLE_WORKER_KEEP_ALIVE_NS, DEFAULT_SCHEDULER_NAME
) {
......
}
internal open class SchedulerCoroutineDispatcher(
private val corePoolSize: Int = CORE_POOL_SIZE,
private val maxPoolSize: Int = MAX_POOL_SIZE,
private val idleWorkerKeepAliveNs: Long = IDLE_WORKER_KEEP_ALIVE_NS,
// schedulerName的值默认就是 "DefaultDispatcher"
private val schedulerName: String = "CoroutineScheduler",
) : ExecutorCoroutineDispatcher() {
override val executor: Executor
get() = coroutineScheduler
// This is variable for test purposes, so that we can reinitialize from clean state
private var coroutineScheduler = createScheduler()
private fun createScheduler() =
// 使用 CoroutineScheduler 作为调度器
CoroutineScheduler(corePoolSize, maxPoolSize, idleWorkerKeepAliveNs, schedulerName)
override fun dispatch(context: CoroutineContext, block: Runnable): Unit = coroutineScheduler.dispatch(block)
override fun dispatchYield(context: CoroutineContext, block: Runnable): Unit =
coroutineScheduler.dispatch(block, tailDispatch = true)
internal fun dispatchWithContext(block: Runnable, context: TaskContext, tailDispatch: Boolean) {
coroutineScheduler.dispatch(block, context, tailDispatch)
}
....
}
internal class CoroutineScheduler(
// 核心线程数量,保证核心线程的存活,核心线程干cpu密集型任务,io任务(Blocking)不能占有许可(会主动释放)
@JvmField val corePoolSize: Int,
// 最大线程数量
@JvmField val maxPoolSize: Int,
// 空闲线程可以存活的时间,大于corePoolSize的数量的线程闲下来时都是空闲线程
@JvmField val idleWorkerKeepAliveNs: Long = IDLE_WORKER_KEEP_ALIVE_NS,
// 调度器的名字
@JvmField val schedulerName: String = DEFAULT_SCHEDULER_NAME
) : Executor, Closeable {
// CPU密集型任务队列
@JvmField
val globalCpuQueue = GlobalQueue()
// IO型任务队列
@JvmField
val globalBlockingQueue = GlobalQueue()
// 处于parked状态的线程都在这个栈上,这个值是栈顶的值,这个值分成2部分,PARKED_INDEX表示一个workers数组索引位置
// 通过这个索引可以在workers数组中找到这个worker,另一部分就是版本号,记录被修改的次数
/**
* |------------------------------------|----------------------|
* | PARKED_VERSION(43bit) | PARKED_INDEX(21bit) |
* |------------------------------------|--------------------——|
*/
private val parkedWorkersStack = atomic(0L)
// 存储线程的数组,workers[0]这个位置不用,是null。从1开始才是有效的worker
@JvmField
val workers = ResizableAtomicArray<Worker>((corePoolSize + 1) * 2)
/**
* |------------------------------------|---------------------|----------------------|
* | cpu permit(22bit) | BLOCKING(21bit) | CREATED(21bit) |
* |------------------------------------|---------------------|----------------------|
*/
// 也就是说这里的cpu permit初始值是corePoolSize
private val controlState = atomic(corePoolSize.toLong() shl CPU_PERMITS_SHIFT)
// 当前创建的线程数量
private val createdWorkers: Int inline get() = (controlState.value and CREATED_MASK).toInt()
// cpu permit的数量,初始值是corePoolSize
private val availableCpuPermits: Int inline get() = availableCpuPermits(controlState.value)
// 计算当前创建的线程数量
private inline fun createdWorkers(state: Long): Int = (state and CREATED_MASK).toInt()
// 计算当前阻塞的线程数量
private inline fun blockingTasks(state: Long): Int = (state and BLOCKING_MASK shr BLOCKING_SHIFT).toInt()
inline fun availableCpuPermits(state: Long): Int = (state and CPU_PERMITS_MASK shr CPU_PERMITS_SHIFT).