RxJava:如何使用缓冲区和快速消费者来实现缓慢的消费者到同一个源?

时间:2016-09-01 22:47:15

标签: buffer rx-java reactive-programming throttling backpressure

在玩各种背压场景时,我实现了一个用户缓慢使用缓冲区的情况,而另一个用户使用任何抛出的内容。那是使用Scala和Akka Streams。如果您愿意,可以看到代码here以及运行它的测试here

我通常会尝试开发一个RxJava版本进行比较,但我仍然坚持这个版本。在Akka Streams中,我可以构建一个图形,其中一个源在2个通道上广播,并且具有慢速接收器和快速接收器从这些通道消耗。每个通道可以独立应用缓冲和限制。在RxJava中,有share运算符用于广播,但缓冲和限制逻辑不在Subscriber上,而在Observable上。因此,我不确定如何应用缓冲和限制,并且不会影响两个订户。 Akka Streams和RxJava都是Rx的实现,我希望能够得到我想要的东西。

这是我尝试做的pictorial version

2 个答案:

答案 0 :(得分:1)

这样的东西?

import rx.Observable;
import rx.observables.ConnectableObservable;

import java.util.concurrent.TimeUnit;

public class Test {
    public static void main(String[] args) {

        //emits Long every 100 milliseconds, and publishes to all Subscribers simultaneously through ConnectableObservable
        ConnectableObservable<Long> source = Observable.interval(100, TimeUnit.MILLISECONDS).publish();

        //buffers emissions into Lists within 1 second durations, and first Subscriber prints them
        source.buffer(1,TimeUnit.SECONDS).subscribe(System.out::println);

        //no buffering, just push emissions directly to this second Subscriber which prints them
        source.subscribe(System.out::println);

        //start firing emissions now both Subscribers are connected
        source.connect();

        //sleep to keep program alive for 10 seconds
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Subscriber没有节流或任何运营商的概念。这些是在Observable侧通过各种运算符完成的,这些运算符产生不同的Observable实现。 Subscriber非常愚蠢,只是消耗排放作为Observable链中的最后一步。排放发生在哪个线程上是不可知的,更不用说Observable将项目传递给它是否被限制。

答案 1 :(得分:0)

如果您想要不同的背压行为,您应该能够以不同的方式为不同的订阅者装饰shared()观察者。

例如

Observable<Integer> source = Observable.interval(0, 1, TimeUnit.SECONDS).share();

// Naked source for fast consumers.
Observable<Integer> fast = source; 

// Buffer for slow consumers that use backpressure.
Observable<Integer> slow = source.onBackpressureBuffer();

上述fastslow的订阅者最终将使用相同的共享源。

请注意,fast不会对背压做出响应,因为interval不会对背压做出响应。

onBackpressureXXX()有不同的风格可以让你获得不同的行为。