You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin:使用协程实现Executors.newSingleThreadExecutor的执行效果

如何用Kotlin协程实现任务排队并顺序执行?

问题背景

使用Executors.newSingleThreadExecutor时,任务会按注册顺序排队执行,输出严格按0到10的顺序。但尝试用Dispatchers.Default.limitedParallelism(1)实现相同效果时,输出却是奇数先完成,顺序不符合预期。

原因分析

limitedParallelism(1)仅限制同时运行的协程数量为1,但协程的挂起(比如delay)是非阻塞操作:当第一个协程(i=0)执行delay(2000)时,会让出当前线程,调度器会立即启动下一个等待的协程(i=1)。由于i=1的delay(1000)耗时更短,会先完成并输出,最终导致奇数先被打印。

而newSingleThreadExecutor中的Thread.sleep是阻塞线程的操作,线程被占用时无法处理其他任务,必须等当前任务完全执行完才会取下一个任务,因此能保证顺序。

解决方法

要实现协程任务的严格顺序执行,需确保前一个任务完全完成后,再启动下一个任务,有三种常用方案:

方案1:使用Mutex串行化任务

通过互斥锁(Mutex)将每个任务的执行逻辑包裹,确保同一时间只有一个协程执行任务块:

val mutex = Mutex()
val dispatcher = Dispatchers.Default.limitedParallelism(1)

(0..10).forEach { i ->
    lifecycleScope.launch(dispatcher) {
        mutex.withLock {
            if (i % 2 == 0) {
                delay(2000)
            } else {
                delay(1000)
            }
            println(i)
        }
    }
}

withLock会自动处理锁的获取与释放,即使协程挂起(比如delay),锁也会保持,直到当前任务块执行完毕,下一个协程才能获取锁执行。

方案2:顺序启动并等待协程完成

在同一个协程中,逐个启动任务协程并调用join()等待其完成,再启动下一个:

lifecycleScope.launch {
    (0..10).forEach { i ->
        launch {
            if (i % 2 == 0) {
                delay(2000)
            } else {
                delay(1000)
            }
            println(i)
        }.join() // 等待当前协程执行完毕,再处理下一个任务
    }
}

这种方式更直观,完全按任务注册顺序依次执行,无需额外调度器配置。

方案3:使用Channel实现任务队列

通过Channel作为任务队列,单个消费者协程按顺序处理任务:

val taskChannel = Channel<Int>(Channel.UNLIMITED)

// 启动单个消费者协程处理任务
lifecycleScope.launch {
    for (i in taskChannel) {
        if (i % 2 == 0) {
            delay(2000)
        } else {
            delay(1000)
        }
        println(i)
    }
}

// 发送任务到队列
(0..10).forEach { i ->
    lifecycleScope.launch {
        taskChannel.send(i)
    }
}

这种方式适合任务动态添加的场景,消费者协程会严格按接收顺序处理每个任务。

总结

limitedParallelism(1)无法保证任务执行顺序的核心是协程挂起会让出线程,要实现严格串行执行,需通过互斥锁、顺序等待或任务队列的方式,确保任务按注册顺序依次完成。

内容的提问来源于stack exchange,提问作者Bugs Happen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 04:24:25