Kotlin协程异步代码运行为何需指定Dispatcher调度器?
Kotlin协程launch需指定调度器才并行的原因
核心逻辑一句话:协程的执行线程由调度器决定,单线程调度器只能串行,多线程调度器才能实现并行。
1. 未指定调度器时为啥是串行?
你应该是在runBlocking作用域里启动的协程——runBlocking默认使用绑定到当前调用线程的单线程调度器,所有在它内部启动且未指定调度器的协程,都会继承这个单线程上下文。
如果你的协程代码包含阻塞操作(比如Thread.sleep()),这个单线程会被第一个协程完全占用,第二个协程必须等第一个执行完毕才能启动,最终就会输出start A → finish A → start B → finish B的串行结果。哪怕用delay()这类挂起函数,如果代码是纯同步无挂起的逻辑,同样会串行执行。
对应你场景的代码示例:
runBlocking { // 继承runBlocking的单线程调度器 launch { println("start A") Thread.sleep(1000) // 阻塞线程 println("finish A") } launch { println("start B") Thread.sleep(1000) println("finish B") } }
2. 指定Dispatchers.Default后为啥能并行?
Dispatchers.Default是Kotlin提供的多线程调度器,它背后是一个与CPU核心数匹配的共享线程池。
当你用launch(Dispatchers.Default)启动协程时,两个协程会被分配到线程池中的不同线程(或空闲线程)同时执行,阻塞操作各自占用不同线程,自然就能产生并行输出(比如start A → start B → finish A → finish B这类交错结果)。
对应代码示例:
runBlocking { launch(Dispatchers.Default) { println("start A") Thread.sleep(1000) println("finish A") } launch(Dispatchers.Default) { println("start B") Thread.sleep(1000) println("finish B") } }
3. 额外补充
- 协程本身不是线程,它的并行能力完全依赖调度器提供的多线程资源。
- 除了
Dispatchers.Default,Dispatchers.IO也是常用的多线程调度器,专门处理IO密集型任务;CPU密集型任务用Default更合适。 runBlocking的单线程默认调度器是故意设计的,目的是让其作用域内的代码在调用线程上顺序执行,避免不必要的线程切换复杂度。
内容的提问来源于stack exchange,提问作者Stefan Haberl
相关产品推荐
相关产品推荐

