Default: 默认情况下,此调度器使用的最大并行数等于 CPU 内核数,但至少为 2。 并行度 X 保证在这个调度器中并行执行的任务不超过 X 个。
Main: 不管是否已经在 main 线程中,都将会 Handler.post(block) 执行。
Main.immediate:如果已经在 main 线程中,将立即执行,否则将会 Handler.post(block) 执行。
override fun isDispatchNeeded(context: CoroutineContext): Boolean {
return !invokeImmediately || Looper.myLooper() != handler.looper
}
IO: 与 Default 共享线程池,默认为 64 个线程的限制或内核数(以较大者为准)
用协程块 block 创建 Task 时,会标记 mode 为 TASK_PROBABLY_BLOCKING = 1。
添加 Task 后,会增加 blocking 任务数。
CPU线程数 = 已创建线程数 - blocking 任务数 cpuWorkers = (created - blocking)
如果 CPU线程数 < 核心线程数,则创建新的线程。
class CoroutineScheduler(
val corePoolSize: Int,
val maxPoolSize: Int,
val idleWorkerKeepAliveNs: Long = IDLE_WORKER_KEEP_ALIVE_NS,
val schedulerName: String = DEFAULT_SCHEDULER_NAME
) : Executor, Closeable
Kotlin 协程定义的线程池,对任务作了 CPU 任务和 Blocking 任务划分。
首先尝试将 Task 添加到当前线程的 localQueue 队列,如果添加失败,则添加到全局的 globalBlockingQueue 或 globalCpuQueue 队列。
val currentWorker = currentWorker()
val notAdded = currentWorker.submitToLocalQueue(task, tailDispatch)
if (notAdded != null) {
if (!addToGlobalQueue(notAdded)) {
// Global queue is closed in the last step of close/shutdown -- no more tasks should be accepted
throw RejectedExecutionException("$schedulerName was terminated")
}
}
private fun tryCreateWorker(state: Long = controlState.value): Boolean {
val created = createdWorkers(state)
val blocking = blockingTasks(state)
val cpuWorkers = (created - blocking).coerceAtLeast(0)
/*
* We check how many threads are there to handle non-blocking work,
* and create one more if we have not enough of them.
*/
if (cpuWorkers < corePoolSize) {
val newCpuWorkers = createNewWorker()
// If we've created the first cpu worker and corePoolSize > 1 then create
// one more (second) cpu worker, so that stealing between them is operational
if (newCpuWorkers == 1 && corePoolSize > 1) createNewWorker()
if (newCpuWorkers > 0) return true
}
return false
}
Unconfined:
withContext(Dispatchers.Unconfined) {
println(1)
withContext(Dispatchers.Unconfined) { // Nested unconfined
println(2)
}
println(3)
}
println("Done")
可以打印“1 2 3”和“1 3 2”,这是一个可以更改的实现细节。但是可以保证只有当两个 withContext 都完成时才会打印“Done”。