Skip to content

启动模式详解 (CoroutineStart)

源:CoroutineStart API

大部分开发者只使用默认行为,但特定场景下,选择正确的 CoroutineStart 模式能显著提升性能或保证逻辑安全。

模式立即调度?立即挂起?可取消性适用场景
DEFAULT随时可取消常规业务 (90%)
LAZY否 (需 start)随时可取消依赖触发、懒加载
ATOMIC首个挂起点前不可取消关键资源初始化
UNDISPATCHED否 (当前线程跑)随时可取消极致性能优化

1. DEFAULT (默认)

调用 launch 后,协程立即进入调度器的队列。

  • 注意:只是进入队列,并不代表立即执行。如果调度器忙,它需要等待。

2. LAZY (懒加载)

协程创建后呈 New 状态,不会执行,直到你调用 job.start()join() / await()

kotlin
val job = launch(start = CoroutineStart.LAZY) {
    // 只有调用 start() 后才会打印
    println("Work started")
}

// ... 做些准备工作 ...
job.start()

3. ATOMIC (原子性)

这是一种“强硬”的启动模式。 特点:协程体内的代码直到遇到第一个挂起点(如 delay)之前,免疫取消

kotlin
val job = launch(start = CoroutineStart.ATOMIC) {
    // 即使在外面立即调用了 cancel(),这里也一定会在取消前执行
    allocateCriticalResources() 
    
    delay(100) // ---> 只有在这里才会检查取消并抛出异常
}
job.cancel()

4. UNDISPATCHED (不调度/立即执行)

这是性能黑客的利器。它让协程像普通函数一样,在当前线程立即同步执行,直到遇到第一个挂起点。

kotlin
launch(Dispatchers.Default, start = CoroutineStart.UNDISPATCHED) {
    // 1. 立即在当前线程 (e.g., Main) 执行,不发生线程切换
    println("Thread: ${Thread.currentThread().name}") 
    
    delay(100) // 2. 挂起
    
    // 3. 恢复时,才会遵守 Dispatchers.Default,切换到后台线程
    println("Thread: ${Thread.currentThread().name}") 
}

性能优势

它节省了第一次 context switching 和 dispatching 的开销。如果你有一堆微小的协程任务,且前一部分逻辑是非阻塞的,使用此模式可显著减少 CPU 消耗。