RxJava调度器的用例

RxJava调度器的用例,java,multithreading,thread-safety,rx-java,rx-android,Java,Multithreading,Thread Safety,Rx Java,Rx Android,在RxJava中,有以下选项可供选择: immediate():创建并返回在当前线程上立即执行工作的计划程序 trampoline():创建并返回一个调度程序,该调度程序将当前线程上的工作排队,以便在当前工作完成后执行 newThread():创建并返回一个调度程序,该调度程序为每个工作单元创建一个新线程 计算():创建并返回用于计算工作的计划程序。这可以用于事件循环、处理回调和其他计算工作。不要在此计划程序上执行IO绑定工作。使用调度程序。io() io():创建并返回用于io绑定工作的计划程

在RxJava中,有以下选项可供选择:

  • immediate():创建并返回在当前线程上立即执行工作的计划程序

  • trampoline():创建并返回一个调度程序,该调度程序将当前线程上的工作排队,以便在当前工作完成后执行

  • newThread():创建并返回一个调度程序,该调度程序为每个工作单元创建一个新线程

  • 计算():创建并返回用于计算工作的计划程序。这可以用于事件循环、处理回调和其他计算工作。不要在此计划程序上执行IO绑定工作。使用调度程序。io()

  • io():创建并返回用于io绑定工作的计划程序。 该实现由执行器线程池支持,该线程池将根据需要增长。这可用于异步执行阻塞IO。不要在此计划程序上执行计算工作。使用调度程序。计算()

  • 问题: 前3个调度器是非常不言自明的;然而,我对计算和io有点困惑

  • 什么是“IO绑定工作”?它是否用于处理流(
    java.io
    )和文件(
    java.nio.files
    )?它用于数据库查询吗?它是用于下载文件还是访问RESTAPI
  • 计算()与新线程()有何不同?是不是所有计算()调用每次都在一个(后台)线程上,而不是在一个新的(后台)线程上
  • 为什么在执行IO工作时调用计算()不好
  • 为什么在做计算工作时调用io()不好

  • 很好的问题,我认为文档可以做得更详细一些

  • io()
    由一个无限的线程池支持,是一种用于非计算密集型任务的东西,这种东西不会给CPU带来太多负载。因此,与文件系统的交互、与不同主机上的数据库或服务的交互就是很好的例子
  • computation()
    由大小等于可用处理器数量的有界线程池支持。如果您试图在超过可用处理器的范围内并行安排CPU密集型工作(例如使用
    newThread()
    ),那么您将面临线程创建开销和上下文切换开销,因为线程争夺处理器,这可能会对性能造成巨大影响
  • 最好将
    computation()
    留给CPU密集型工作,否则您将无法获得良好的CPU利用率
  • 调用
    io()
    进行计算工作是不好的,原因如2所述
    io()
    是无限的,如果您在
    io()
    上并行调度一千个计算任务,那么这一千个任务中的每一个都将有自己的线程,并且都将与CPU竞争,从而产生上下文切换成本

  • 最重要的一点是,Schedulers.io和Schedulers.computation都由无界线程池支持,而不是问题中提到的其他线程池。此特性仅由调度器共享。如果执行器是使用newCachedThreadPool创建的(与自动回收线程池无绑定),则从(Executor)

    正如之前的回复和web上的多篇文章中充分解释的那样,应谨慎使用Schedulers.io和Schedulers.computation,因为它们以自己的名义针对工作类型进行了优化。但是,在我看来,它们最重要的作用是为反应流提供真正的并发性

    与新来者的信念相反,反应流不是天生并发的,而是天生异步和顺序的。正是由于这个原因,Schedulers.io只能在I/O操作阻塞时使用(例如:使用诸如Apache IOUtils FileUtils.readFileAsString(…)之类的阻塞命令),因此将冻结调用线程,直到操作完成

    使用诸如Java AsynchronousFileChannel(…)之类的异步方法不会在操作期间阻塞调用线程,因此没有必要使用单独的线程。事实上,Schedulers.io线程并不适合异步操作,因为它们不运行事件循环,回调也不会。。。被叫来

    同样的逻辑也适用于数据库访问或远程API调用。如果可以使用异步或反应式API进行调用,请不要使用Schedulers.io

    回到并发。您可能无法访问异步或反应式API以异步或并发地执行I/O操作,因此您唯一的选择是在单独的线程上调度多个调用。唉,反应流在其末端是顺序的,但好消息是flatMap()操作符可以在其核心引入并发性

    并发必须在流构造中构建,通常使用flatMap()操作符。这个强大的操作符可以配置为在内部为flatMap()嵌入函数提供多线程上下文。该上下文由多线程调度程序(如Scheduler.io或Scheduler.computation)提供

    在关于RxJava2的文章中可以找到更多详细信息,在那里可以找到关于如何顺序和并发使用调度器的代码示例和详细解释

    希望这有帮助

    软杰克

    从博客帖子:

    Schedulers.io()由一个无限线程池支持。它用于非CPU密集型I/O工作,包括与文件系统的交互、执行网络调用、数据库交互等。此线程池用于