RxJava中IO调度器线程行为异常问题咨询
Hey,这个问题其实和RxJava里IO调度器的线程复用机制,还有任务调度的逻辑直接相关,咱们一步步拆解清楚:
先明确两个核心机制
Schedulers.io()的线程池特性
它背后用的是可缓存线程池(CachedThreadPool),核心逻辑是:- 有新任务时,优先复用池里的空闲线程
- 没空闲线程就新建一个线程
- 空闲线程闲置满60秒会被自动回收
任务调度的队列逻辑
如果你是通过observeOn(Schedulers.io())让toRandomList之后的流程跑在IO线程,那么每个元素的下游处理逻辑都会被包装成独立任务,扔进IO调度器的任务队列里。线程池里的线程会从队列里依次取任务执行。
两种场景的具体原因
场景1:注释掉chooseString里的sleep代码
这时候chooseString执行速度极快,几乎瞬间就能完成。当第一个任务被线程Thread-1处理完后,Thread-1会回到线程池变成空闲状态,但因为上游发射元素的速度太快,线程池还没来得及把Thread-1标记为可用,就会直接新建Thread-2来处理下一个任务。以此类推,每个元素的处理都会用到新线程,所以你看到“每个发射及后续流程都在独立线程执行”。
场景2:取消sleep代码的注释
这时候chooseString执行耗时变长(sleep会让线程阻塞)。当Thread-1在处理第一个任务时,会一直处于忙碌状态直到sleep结束。上游发射的下一个元素会被包装成任务,放到IO调度器的任务队列里。等Thread-1完成第一个任务后,会立刻从队列里取下一个任务继续执行,不会新建线程。后续所有任务都会被同一个线程依次处理,所以你看到“所有步骤都在同一线程执行”。
你有没有操作失误?
其实这完全是RxJava调度器的正常行为,不算操作失误!如果你的业务场景确实需要每个元素都在独立线程处理(不管任务耗时长短),可以改用Schedulers.newThread()——这个调度器会为每个任务新建线程,不会复用。不过要注意:无限制新建线程可能带来性能问题,所以如果任务数量较多,还是建议用Schedulers.io()的线程复用机制更稳妥。
内容的提问来源于stack exchange,提问作者rascio

