Skip to content

高并发场景下的协程调度与调优


一、 前言

  1. Dispatchers.DefaultDispatchers.IODispatchers.Main的线程池底层区别
  • Dispatchers.Default:适用于CPU密集型任务(计算、JSON解析等),其线程池大小为CPU核心数2X核心数 之间的固定线程池,调度策略是基于 ForkJoinPool 或 kotlin的 CommonPool。如果线程不够,会挂起协程而非扩展线程。

  • Dispatcher.IO: 适用于IO密集型任务(网络请求、数据库、磁盘读写),其线程池大小为 无限制线程池实际64 X 核心数),底层上复用了 Default 线程池,但是允许更多协程切入。适合同时发起大量短时间的IO任务,如果IO操作阻塞时间长,线程会被挂起,释放资源给其他协程。如果把CPU密集任务跑在IO上,可能导致线程数膨胀,调度开销大,甚至OOM。

  • Dispatchers.Main:适用于所有需要与 UI 交互的任务,严格只有一个线程(UI线程),执行时间必须短,超过16ms可能会掉帧,避免 delay()、withContext(IO) 这类长时间操作。

  1. withContext() vs launch() 的调度差异
特性withContext()launch()
是否为挂起函数必须是suspend
是否阻塞当前协程会等待执行完,返回后继续不会阻塞,异步执行
是否返回结果有返回值(像普通函数一样)没有返回值(只能依靠回调或共享变量)
异常传播抛出异常给调用者,可以捕获在同一个CoroutineScope会联动取消
是否是结构化并发
常见用途切换线程并执行任务 + 获取结果启动一个协程处理异步任务

适用总结

  1. 需要结果 → 用 withContext()
  2. 只需要并发启动任务 → 用 launch()
  3. 复杂任务组合 → async + await 更合适
  4. 大量 withContext() 嵌套需慎用,易调度开销过大

示例如下

方法一:用 withContext() 穿行处理(低效)

kotlin
suspend fun loadDataSerial(): UserOrderInfo {
    val user = withContext(Dispatchers.IO) {
        getUserInfo() // 网络请求
    }

    val orders = withContext(Dispatchers.IO) {
        getOrderList(user.id) // 数据库加载或网络请求
    }

    return UserOrderInfo(user, orders)
}

缺点:两个请求是串行的,第二个必须等第一个完成 → 总耗时 = A + B,不适合高并发聚合场景。

方法二:用 async + await 并发处理(高效)

kotlin
suspend fun loadDataConcurrent(): UserOrderInfo = CoroutineScope {
    val userDefered = async(Dispatchers.IO) {
        getUserInfo()
    }

    val ordersDeferred = async(Dispatchers.IO) {
        val user = userDefered.await()
        getOrderList(user.id)
    }

    val user = userDefered.await()
    val orders = ordersDeferred.await()

    UserOrderInfo(user, orders)
}

总耗时 ≈ Max(A, B)

以上两种方法的区别在于 async 启动的是 独立协程,而 withContext() 是“切线程 + 等执行完再返回”

二、调度策略分析:Default vs IO vs Unconfined

三、SharedFlow、Channel 高并发背压

四、协程性能调优技巧

  1. 尽量减少 withContext(IO) 嵌套调用,切换开销大
  2. 大量计算使用 Default,但也要限流(Semaphore、Chunk 分片)
  3. 利用 SupervisorScope 局部处理异常防止协程传播 cancel

五、调试与排查

DebugProbes.install() + DebugProbes.dumpCoroutines() 打印活跃协程信息

Released under the MIT License.