项目调用方式
private suspend fun upLog(resource_id: String): Boolean {
var success = false
withContext(Dispatchers.IO) {
//做一些耗时操作,比如请求网络
}
return success
}
源码追踪 Dispatchers类,发现是个静态变量
@JvmStatic
public val IO: CoroutineDispatcher = DefaultScheduler.IO
DefaultScheduler#IO
val IO = blocking(systemProp(IO_PARALLELISM_PROPERTY_NAME, 64.coerceAtLeast(AVAILABLE_PROCESSORS)))
看下blocking方法创建了LimitingDispatcher对象
public fun blocking(parallelism: Int = BLOCKING_DEFAULT_PARALLELISM): CoroutineDispatcher {
require(parallelism > 0) { "Expected positive parallelism level, but have $parallelism" }
return LimitingDispatcher(this, parallelism, TaskMode.PROBABLY_BLOCKING)
}
LimitingDispatcher实现了Executor接口,看来是类似线程池的逻辑
LimitingDispatcher#execute
override fun execute(command: Runnable) = dispatch(command, false)
dispatch又调用了dispatchWithContext
internal fun dispatchWithContext(block: Runnable, context: TaskContext, fair: Boolean) {
try {
coroutineScheduler.dispatch(block, context, fair)
} catch (e: RejectedExecutionException) {
// Context shouldn't be lost here to properly invoke before/after task
DefaultExecutor.enqueue(coroutineScheduler.createTask(block, context))
}
}
CoroutineScheduler#dispatch方法
fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, fair: Boolean = false) {
trackTask() // this is needed for virtual time support
//创建一个TaskImpl对象把block又包裹一层
val task = createTask(block, taskContext)
// try to submit the task to the local queue and act depending on the result
when (submitToLocalQueue(task, fair)) {
ADDED -> return
NOT_ADDED -> {
// try to offload task to global queue
if (!globalQueue.addLast(task)) {
// Global queue is closed in the last step of close/shutdown -- no more tasks should be accepted
throw RejectedExecutionException("$schedulerName was terminated")
}
requestCpuWorker()
}
else -> requestCpuWorker() // ask for help
}
}
requestCpuWorker方法,会调用createNewWorker创建线程执行任务
/*
* 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
}
createNewWorker方法
/*
* Returns the number of CPU workers after this function (including new worker) or
* 0 if no worker was created.
*/
private fun createNewWorker(): Int {
synchronized(workers) {
// Make sure we're not trying to resurrect terminated scheduler
if (isTerminated) return -1
val state = controlState.value
val created = createdWorkers(state)
val blocking = blockingWorkers(state)
val cpuWorkers = created - blocking
// Double check for overprovision
if (cpuWorkers >= corePoolSize) return 0
if (created >= maxPoolSize || cpuPermits.availablePermits() == 0) return 0
// start & register new worker, commit index only after successful creation
val newIndex = createdWorkers + 1
require(newIndex > 0 && workers[newIndex] == null)
//创建一个Worker对象并调用start()方法
val worker = Worker(newIndex).apply { start() }
require(newIndex == incrementCreatedWorkers())
workers[newIndex] = worker
return cpuWorkers + 1
}
}
Worker其实就是线程
internal inner class Worker private constructor() : Thread()
核心线程池数至少是两个。
@JvmField
internal val CORE_POOL_SIZE = systemProp(
"kotlinx.coroutines.scheduler.core.pool.size",
AVAILABLE_PROCESSORS.coerceAtLeast(2), // !!! at least two here
minValue = CoroutineScheduler.MIN_SUPPORTED_POOL_SIZE
)
AVAILABLE_PROCESSORS
internal val AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors()
fun dispatch(block: Runnable, taskContext: TaskContext = NonBlockingContext, fair: Boolean = false) {
trackTask() // this is needed for virtual time support
val task = createTask(block, taskContext)
// try to submit the task to the local queue and act depending on the result
when (submitToLocalQueue(task, fair)) {
ADDED -> return
NOT_ADDED -> {
// try to offload task to global queue
if (!globalQueue.addLast(task)) {
// Global queue is closed in the last step of close/shutdown -- no more tasks should be accepted
throw RejectedExecutionException("$schedulerName was terminated")
}
requestCpuWorker()
}
else -> requestCpuWorker() // ask for help
}
}
requestCpuWorker方法内部会判断当前线程个数有没有超过核心线程数,如果没超过,就继续创建线程执行任务。
/*
* 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
}
createNewWorker方法
private fun createNewWorker(): Int {
synchronized(workers) {
// Make sure we're not trying to resurrect terminated scheduler
if (isTerminated) return -1
val state = controlState.value
val created = createdWorkers(state)
val blocking = blockingWorkers(state)
val cpuWorkers = created - blocking
// Double check for overprovision
if (cpuWorkers >= corePoolSize) return 0
if (created >= maxPoolSize || cpuPermits.availablePermits() == 0) return 0
// start & register new worker, commit index only after successful creation
val newIndex = createdWorkers + 1
require(newIndex > 0 && workers[newIndex] == null)
//创建线程并开启start
val worker = Worker(newIndex).apply { start() }
require(newIndex == incrementCreatedWorkers())
workers[newIndex] = worker
return cpuWorkers + 1
}
}
Woeker#run方法,开启while循环,执行任务。也就是任务被执行的时候
override fun run() {
var wasIdle = false // local variable to avoid extra idleReset invocations when tasks repeatedly arrive
while (!isTerminated && state != WorkerState.TERMINATED) {
val task = findTask()
if (task == null) {
// Wait for a job with potential park
if (state == WorkerState.CPU_ACQUIRED) {
cpuWorkerIdle()
} else {
blockingWorkerIdle()
}
wasIdle = true
} else {
// Note: read task.mode before running the task, because Task object will be reused after run
val taskMode = task.mode
if (wasIdle) {
idleReset(taskMode)
wasIdle = false
}
beforeTask(taskMode, task.submissionTime)
runSafely(task)
afterTask(taskMode)
}
}
tryReleaseCpu(WorkerState.TERMINATED)
}