3

为什么它们用于不同类型的任务?在处理计算任务与 io 任务时,它们有何不同?

Schedulers.computation() - 用于计算工作,例如事件循环和回调处理;不要将此调度程序用于 I/O(使用 Schedulers.io( ) 代替);默认情况下,线程数等于处理器数


Schedulers.io( ) - 用于 I/O 密集型工作,例如阻塞 I/O 的异步性能,此调度程序由一个线程池支持,该线程池将根据需要增长;对于普通的计算工作,切换到 Schedulers.computation();Schedulers.io() 默认是一个 CachedThreadScheduler,类似于一个带有线程缓存的新线程调度器

4

2 回答 2

9

I/O 和计算是非常不同的工作负载。

计算纯粹受 CPU 限制,因此您希望限制线程的数量,以免它们争夺 CPU 并让自己饿死。如果您有 1000 个线程都试图在 8 个内核上工作,那么您可能会度过一段糟糕的时光。Schedulers.computation() 限制为核心数。

I/O 是不同的,因为虽然它们通常需要一个线程来维护上下文,但它们并不真正使用 CPU——它们只是休眠直到 I/O 完成。在单核机器上进行 1000 次 I/O 操作是非常好的,因为它们大部分时间都处于休眠状态。Schedulers.io() 没有上限,将根据需要生成尽可能多的线程

于 2016-04-08T14:25:27.903 回答
0

最重要的一点是 Schedulers.io 和 Schedulers.computation 都由无限的自动回收线程池支持。只有在使用 newCachedThreadPool(不受自动回收线程池限制)创建 Executor 的情况下,Scheduler.from(Executor) 才共享此特性。

默认情况下, Scheduler.computation配置的线程数等于可用 CPU 的数量,因此计算会尽可能快地执行。您可以增加此数字,但这可能会引入线程切换开销并减慢计算速度。

至于Schedulers.io,你应该只将它用于阻塞 I/O 操作,因为它们会阻塞调用线程。如果您的 I/O 调用是通过异步或反应式 API 进行的,请不要使用它,因为在Scheduler.io上没有回调该调用的机制。

话虽如此,这些调度程序的一个重要作用是为flatMap()运算符提供多线程上下文,从而在反应流的核心实现并发。

从此处的类似问题和有关 RxJava2调度程序并发的文章中找到更多详细信息,您可以在其中找到详细的解释和代码示例。

希望这可以帮助,

软杰克

于 2018-07-19T13:08:14.077 回答