RxJava:用于暂时挂起所选源Observable而没有statefull变量的模式

时间:2017-08-17 19:33:39

标签: design-patterns rx-java reactive-programming

在更大的RxJava应用程序中,我有许多无限源Observable。这些排放合并后由下游观察员处理。然后,处理结果需要用于临时暂停某些源Observable的排放,而非暂停的Observable预计将继续排放,观察者将消耗非暂停的排放。热点Observables在暂停期间发生的任何事件都可以安全地被忽略/删除。

到目前为止,我能够提出的唯一解决方案是应用具有全局,有状态变量的过滤器。下面的代码显示了原理。为简单起见,我将源Observable的逻辑移动到while循环中,然后简单地随机分配暂停/运行决策。此外,源Observables被简单的区间替换(在实际应用程序中,事件是随机的,来自外部源,包含在Observables中)

boolean is1running = true;
boolean is2running = true;
boolean is3running = true;

public void multiStream() {

    Observable<String> ob1 = Observable
            .interval(100, TimeUnit.MILLISECONDS)
            .map(s -> "OB1::" + s)
            .filter(s -> keepRunning(1));

    Observable<String> ob2 = Observable
            .interval(100, TimeUnit.MILLISECONDS)
            .map(s -> "OB2::::" + s)
            .filter(s -> keepRunning(2));

     Observable<String> ob3 = Observable
            .interval(100, TimeUnit.MILLISECONDS)
            .map(s -> "OB3:::::" + s)
            .filter(s -> keepRunning(3));

     Observable<String> finalObs = Observable.merge(ob1, ob2, ob3);

     finalObs.subscribe(s -> System.out.println(s));

     Random randomGenerator = new Random();

     while(true)
     {
         sleep(1000);
         is1running = randomGenerator.nextBoolean();
         is2running = randomGenerator.nextBoolean();
         is3running = randomGenerator.nextBoolean();
     }
}

private boolean keepRunning(int i) {
    switch(i)
    {
        case 1: return is1running;
        case 2: return is2running;
        case 3: return is3running;
    }

    return true;
}

代码似乎有效,但我不满意必须使用全局的有状态变量。

这种情况是否有更好的模式,也符合功能和反应范式?

1 个答案:

答案 0 :(得分:0)

对于这种情况,我经常使用switchMap()运算符。对于您的示例,我们假设每个来源都有一个可观察的boolean,因此ob1Switchob2Switchob3Switch。然后,

Observable<String> ob1 = Observable
        .interval(100, TimeUnit.MILLISECONDS)
        .map(s -> "OB1::" + s);

将由ob1Switch控制:

Observable<String> ob1Switchable = ob1Switch
  .switchMap( switchOn -> switchOn ? ob1 : Observable.never() );

现在,您可以在ob1Switchable使用ob1,而无需使用全局状态。当你想要ob1Switch开启时,你必须保持ob1Switch.onNext(Boolean.TRUE)最新ob1

编辑:作为带有反馈循环的链的示例:

Observable<Integer> eventsPerSecond =
  Observable.merge( ob1Switchable, ob2Switchable, ob3Switchable)
  .buffer(1, TimeUnit.SECONDS )
  .map( buf -> buf.size() );
Observable<Boolean> obs1Switch = eventsPerSecond
  .map( eps -> Boolean.valueOf( eps > LOW_THRESHOLD );
Observable<Boolean> obs2Switch = eventsPerSecond
  .map( eps -> Boolean.valueOf( eps > MEDIUM_THRESHOLD );
Observable<Boolean> obs3Switch = eventsPerSecond
  .map( eps -> Boolean.valueOf( eps > HIGH_THRESHOLD );

有了这些定义,你就可以有一个反馈循环,在你有可持续的事件发生率之前连续关闭来源。