Kotlin Flow中flowOn如何切换上下文?代码运行结果存疑
Kotlin Flow flowOn 线程调度理解误区解答
问题描述
编写了如下Kotlin协程与Flow代码:
CoroutineScope(Main).launch { println("+++ ========= CoroutineScope(IO).launch ${Thread.currentThread().name}") flow { (1..10).forEach { println("+++ in Flow block() forloop ($it), in ${Thread.currentThread().name}") emit(it) } println("+++ in Flow block(), after forloop, ${Thread.currentThread().name}") }.flowOn(Dispatchers.IO) .collect { println("+++ collect's FlowCollector.emit lambda(); $it") println("+++ collect's FlowCollector.emit lambda(); in ${Thread.currentThread().name}") } }
运行后发现:flow构建块在DefaultDispatcher-worker-1线程执行,collect块在main线程执行。原本预期的结果与此相反,疑惑原因。
原因解析
- flowOn的核心作用:
flowOn(Dispatchers.IO)是用来指定**它之前的上游流代码(也就是flow构建块内的逻辑)**的执行线程,而非下游的collect操作线程。 - 下游线程的决定因素:collect作为Flow的终端操作,会继承当前所在协程的上下文线程。你的代码中,外层协程是通过
CoroutineScope(Main).launch在Main线程启动的,所以collect块自然运行在Main线程。 - 上游线程的切换逻辑:flowOn会插入一个线程切换的中间流,将上游flow构建块的执行切换到指定的Dispatcher(这里是IO线程池),所以你看到flow里的循环在IO线程池的
DefaultDispatcher-worker-1线程运行。
简单来说,flowOn只负责“把它前面的流操作搬到指定线程执行”,后面的下游操作线程由调用collect的协程上下文决定,这就是你预期和实际结果相反的核心原因。
内容的提问来源于stack exchange,提问作者lannyf
相关产品推荐
相关产品推荐

