Skip to content

调度器与并发限制

源:Coroutine Dispatchers 官方参考

调度器 (Dispatchers) 决定了协程在哪个线程或线程池上执行。Kotlin 协程的设计哲学是 Explicit Switching (显式切换)

标准调度器

调度器底层实现适用场景线程数上限
MainHandler (Android)UI 更新、轻量级交互1 (主线程)
IO弹性线程池网络、磁盘、数据库64 或 CPU 核心数 (取大值)
Default固定大小线程池CPU 密集型计算 (JSON解析、Diff)CPU 核心数
Unconfined极低开销任务 (测试/日志)N/A

IO 与 Default 的弹性机制

线程池共享

Dispatchers.IODispatchers.Default 实际上共享同一个底层线程池 (CoroutineScheduler)。 这允许线程在执行完 IO 任务后,直接复用以执行 CPU 计算任务,完全消除了线程切换和上下文损耗

线程切换:withContext

withContext 不仅仅是切换线程,它是一个挂起函数

  • 它会等待代码块执行完毕。
  • 它会检查结果返回后的取消状态。
kotlin
suspend fun loadAndShow() {
    // 1. 在主线程启动 (假设)
    showLoading()
    
    // 2. 挂起主线程,切换到 IO 线程执行
    val data = withContext(Dispatchers.IO) {
        // 这里的代码运行在 IO 线程
        loadFromDb() 
    }
    
    // 3. 自动切回主线程
    showContent(data)
}

并发限流:limitedParallelism

Kotlin 1.6 引入的杀手级 API。它不仅能限制并发数,还能用来创建更轻量的单线程调度器(用于处理线程不安全的资源)。

kotlin
// 场景:数据库连接池只有 4 个连接,必须限制同时访问
val dbDispatcher = Dispatchers.IO.limitedParallelism(4)

suspend fun writeToDb() = withContext(dbDispatcher) {
    // 即使启动 100 个协程,同时也只有 4 个在执行
    transaction { ... }
}

替代单线程

limitedParallelism(1) 是替代 newSingleThreadContext 的更优解。它不会真正创建一个新线程,而是复用 IO 线程池中的线程并保证串行执行,避免了创建线程的昂贵开销。