kotlin协程(Dispatchers.IO)

kotlin协程(Dispatchers.IO)

项目调用方式

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() 
总结
  1. kotlin协程,其本质就是操作了java的线程
  2. Dispatchers.IO,内部就是线程池,只不过内部是自己控制线程数量,而不是通过java提供的TreadPoolExector去创建线程池的。

核心线程池数至少是两个。

@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()
  1. 当有任务来的时候,协程是如何工作的?
    当任务执行的时候,CoroutineScheduler#execute方法,会执行到当前类的dispatch,这个方法首先submitToLocalQueue(task, fair),会尝试把任务先加入到线程(Worker)类里面的队列里,如果加入不成功,globalQueue.addLast(task)会加入到全局的队列里面。加入成功会调用requestCpuWorker方法。
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)
        }
可参考文章
  • Kotlin Jetpack 实战:图解协程原理
  • kotlin协程原理

你可能感兴趣的:(Kotlin,源码分析)