Rx java 如何在不丢失发出的项目的情况下暂停可观察的项目?
我有一个Rx java 如何在不丢失发出的项目的情况下暂停可观察的项目?,rx-java,reactivex,Rx Java,Reactivex,我有一个可观察的,每秒都会发出滴答声: Observable.interval(0, 1, TimeUnit.SECONDS) .take(durationInSeconds + 1)); 我想暂停这个观测,这样它就不会发出数字,并根据需要恢复它 有一些问题: 根据ObservableJavadoc,interval操作符不支持背压 RxJava wiki关于有一节关于Callstack阻塞作为背压的流量控制替代方案: 处理生产过剩可观察对象的另一种方法是阻止调用堆栈(停止控制生产
可观察的,每秒都会发出滴答声:
Observable.interval(0, 1, TimeUnit.SECONDS)
.take(durationInSeconds + 1));
我想暂停这个观测,这样它就不会发出数字,并根据需要恢复它
有一些问题:
- 根据
Observable
Javadoc,interval
操作符不支持背压
- RxJava wiki关于有一节关于Callstack阻塞作为背压的流量控制替代方案:
处理生产过剩可观察对象的另一种方法是阻止调用堆栈(停止控制生产过剩可观察对象的线程)。这有违背Rx的“反应性”和非阻塞模型的缺点。但是,如果有问题的可观察对象位于可以安全阻止的线程上,那么这可能是一个可行的选项目前RxJava没有公开任何操作符来实现这一点。
是否有方法暂停可观察到的间隔
?或者我应该通过一些背压支持来实现我自己的“滴答声”?有很多方法可以做到这一点。例如,您仍然可以使用interval()
并维护两个附加状态:例如布尔标志“暂停”和计数器
public static final Observable<Long> pausableInterval(
final AtomicBoolean paused, long initial, long interval, TimeUnit unit, Scheduler scheduler) {
final AtomicLong counter = new AtomicLong();
return Observable.interval(initial, interval, unit, scheduler)
.filter(tick -> !paused.get())
.map(tick -> counter.getAndIncrement());
}
公共静态最终可观测pausableInterval(
最终原子逻辑(暂停、长初始、长间隔、时间单位、调度程序){
最终AtomicLong计数器=新的AtomicLong();
返回可观察的间隔(初始、间隔、单位、调度程序)
.filter(勾选->!暂停.get())
.map(勾选->计数器.getAndIncrement());
}
然后,您只需调用paused.set(true/false)来暂停/恢复
编辑2016-06-04
上面的解决方案有一个小问题。
如果我们多次重用可观察实例,它将从上次取消订阅时的值开始。例如:
Observable<Long> o = pausableInterval(...)
List<Long> list1 = o.take(5).toList().toBlocking().single();
List<Long> list2 = o.take(5).toList().toBlocking().single();
Observable o=pausableInterval(…)
List list1=o.take(5.toList().toBlocking().single();
List list2=o.take(5.toList().toBlocking().single();
虽然list1预期为[0,1,2,3,4],但list2实际为[5,6,7,8,9]。
如果上述行为不符合要求,则必须将可观察对象设置为无状态。这可以通过scan()运算符实现。
修订版可以如下所示:
public static final Observable<Long> pausableInterval(final AtomicBoolean pause, final long initialDelay,
final long period, TimeUnit unit, Scheduler scheduler) {
return Observable.interval(initialDelay, period, unit, scheduler)
.filter(tick->!pause.get())
.scan((acc,tick)->acc + 1);
}
公共静态最终可观测pausableInterval(最终原子布尔暂停,最终长初始延迟,
最终长周期、时间单位、调度程序){
返回可观察间隔(初始延迟、周期、单位、调度程序)
.filter(勾选->!暂停.get())
.扫描((acc,勾选)->acc+1);
}
或者,如果您不希望依赖Java 8和lambdas,可以使用Java 6+兼容代码执行类似操作:
让我想起了你为什么要使用锁定操作员?没有托比,你就不能工作?或者如何在没有Toblock操作符的情况下订阅此事件?Toblock只是用于演示或单元测试。这只是为了确保您的单元测试不会在可观察对象完成之前退出。您可以像任何其他可观察对象一样异步运行它。