rxjava 2中BackpressureStrategy.BUFFER和onBackpressureBuffer运算符之间的区别

时间:2017-05-12 09:29:20

标签: java stream rx-java backpressure

我是反应式编程世界的新手,我正在尝试使用rxjava创建一个简单的背压感知消息处理。

以下是我想要实现的工作流程:

  1. 可以继续使用字符串流。

  2. 执行耗时的操作并将消息更改为另一个字符串

  3. 执行另一项耗时的操作。

  4. 现在我使用以下代码:

    {
        Flowable.create(subscriber -> {
                 some_stream.forEach(data -> {
                    subscriber.onNext(data);
                });
            }, BackpressureStrategy.BUFFER).
        subscribeOn(Schedulers.io()). // Data emission will run io scheduler
        observeOn(Schedulers.computation()). // Map operation will run on computation scheduler
        map(val -> Time_Consuming_Task(val)). // Task returns another string
        observeOn(Schedulers.io()).  / Next consumer will run on computation scheduler
        subscribe(val -> Another_Time_Consuming_Task(val));
    }
    

    现在对于小型操作,我没有看到任何与背压有关的问题。

    但对于大流,我不知道它会如何表现。

    现在我的问题是: -

    1. BackpressureStrategy.BUFFER 时的默认缓冲区大小是什么?数据在哪里缓冲?

    2. 如果我想在每次耗费任务之前创建两个背压缓冲区,我应该使用 onBackpressureBuffer运算符怎么办?

    3. 如果缓冲区已满,我不想丢失数据,我想在这种情况下等待什么?

1 个答案:

答案 0 :(得分:1)

回答你的问题:

1。默认缓冲区大小因平台而异。在JVM上,每个环缓冲区有128个项目,在Android上它是16个项目( Source

这比之前的1024降低了(你可以看到在RxJava here中实现的更改)。还有一个系统属性,您可以根据需要自行调整它:

System.setProperty("rx.ring-buffer.size", "8");

因为它们被称为环形缓冲区,它们存储在内存中。您可以阅读有关他们的更多信息here

2。 &安培; 3.如果它满了,它就会开始覆盖它自己。在这种情况下,请使用onBackpressureBuffer

  

循环缓冲区的结果是当它已满并执行后续写入时,它会开始覆盖最旧的数据。

引用wiki文章关于Circular buffer

当您知道rx.ring-buffer.size时,您可以做的最好的事情就是使用RxJava 2中给出的以下API:

onBackpressureBuffer(int capacity, // This is the given bound, not a setter for the ring buffer
    Action0 onOverflow, // The desired action to execute
    BackpressureOverflow.Strategy strategy) // The desired strategy to use

同样,我不能说得更好,让我引用Backpressure (2.0)上的RxJava wiki:

  

BackpressureOverflow.Strategy实际上是一个接口,但是BackpressureOverflow类提供了4个静态字段,其实现代表了典型的操作:

     
      
  • ON_OVERFLOW_ERROR:这是前两次重载的默认行为,表示BufferOverflowException
  •   
  • ON_OVERFLOW_DEFAULT:目前与ON_OVERFLOW_ERROR
  • 相同   
  • ON_OVERFLOW_DROP_LATEST:如果发生溢出,将简单地忽略当前值,并且只有在下游请求时才会传递旧值。
  •   
  • ON_OVERFLOW_DROP_OLDEST:删除缓冲区中最旧的元素并将当前值添加到缓冲区中。
  •   
     

请注意,最后两个策略会导致流不连续,因为它们会丢弃元素。此外,他们不会发出BufferOverflowException信号。

以下是一个例子:

Flowable.range(1, 1_000_000)
          .onBackpressureBuffer(16, () -> { },
              BufferOverflowStrategy.ON_OVERFLOW_DROP_OLDEST)
          .observeOn(Schedulers.computation())
          .subscribe(e -> { }, Throwable::printStackTrace);

值得注意的是:

  

RxJava 2.x中的Observable类型没有背压概念。实施Observable与默认使用onBackpressureBuffer()实际上相同。 UI事件,一次性网络请求和状态更改都应该使用此方法。 CompletableMaybeSingle类型也可以指示此行为。

     

如果您需要支持背压,RxJava 2.x的新类Flowable与RxJava 1.x中的Observable类似的背压感知。但是,更新后的库现在需要明确选择背压策略以防止出现意外MissingBackpressureExceptions

了解更多: