我正在尝试定期发出事件(每150ms),即使上游的observable会更快地发送事件。
但即使我已拨打MissingBackpressureException
onBackpressureBlock()
代码:
SerializedSubject<QuotationMarker, QuotationMarker> subject = new SerializedSubject<> (PublishSubject.create());
return subject
.subscribeOn(Schedulers.computation())
.doOnSubscribe(() -> {
NetworkRequestsManager.instance().queryQuotations(productId).subscribe(quotation -> {
Log.d(TAG, "new quotation " + quotation.hashCode());
NetworkRequestsManager.instance().getSeller(quotation.sellerId)
.subscribe(seller -> {
for (Outlet outlet : seller.outlets) {
if (outlet.latitude != null && outlet.longitude != null)
subject.onNext(new QuotationMarker(outlet, quotation.price));
}
},
error -> Log.fatalError(new RuntimeException(error)));
},
error -> Log.fatalError(new RuntimeException(error)));
})
.doOnError(throwable -> Log.fatalError(new RuntimeException(
"error response in subscribe after doOnSubscribe",
throwable)))
// combine with another observable that emits items regularly (every 100ms)
// so that a new event is received every 100ms :
// also, first event itself is delayed.
.zipWith(Observable.interval(150, TimeUnit.MILLISECONDS),
(seller, aLong) -> seller)
.onBackpressureBlock() // prevent zipWith Observer.interval from throwing MissingBackpressureException s
.doOnError(throwable -> Log.fatalError(new RuntimeException(
"error response after onBackpressureBlock()",
throwable))); // <-- error is thrown here
迹:
05-06 00:38:25.532 28106-28166/com.instano.buyer W/System.err﹕ java.lang.RuntimeException: error response after onBackpressureBlock()
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at com.instano.retailer.instano.application.controller.Quotations.lambda$fetchQuotationMarkersForProduct$59(Quotations.java:67)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at com.instano.retailer.instano.application.controller.Quotations.access$lambda$5(Quotations.java)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at com.instano.retailer.instano.application.controller.Quotations$$Lambda$8.call(Unknown Source)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.Observable$11.onError(Observable.java:4193)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:65)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorOnBackpressureBlock$BlockingSubscriber.complete(OperatorOnBackpressureBlock.java:81)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.util.BackpressureDrainManager.drain(BackpressureDrainManager.java:190)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.util.BackpressureDrainManager.terminateAndDrain(BackpressureDrainManager.java:129)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorOnBackpressureBlock$BlockingSubscriber.onError(OperatorOnBackpressureBlock.java:68)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorZip$Zip$InnerSubscriber.onError(OperatorZip.java:324)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorZip$Zip$InnerSubscriber.onNext(OperatorZip.java:332)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OnSubscribeTimerPeriodically$1.call(OnSubscribeTimerPeriodically.java:51)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.Scheduler$Worker$1.call(Scheduler.java:120)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390)
05-06 00:38:25.572 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:234)
05-06 00:38:25.582 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:153)
05-06 00:38:25.592 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:267)
05-06 00:38:25.602 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
05-06 00:38:25.602 28106-28166/com.instano.buyer W/System.err﹕ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
05-06 00:38:25.602 28106-28166/com.instano.buyer W/System.err﹕ at java.lang.Thread.run(Thread.java:841)
05-06 00:38:25.602 28106-28166/com.instano.buyer W/System.err﹕ Caused by: rx.exceptions.MissingBackpressureException
05-06 00:38:25.612 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.util.RxRingBuffer.onNext(RxRingBuffer.java:349)
05-06 00:38:25.642 28106-28166/com.instano.buyer W/System.err﹕ at rx.internal.operators.OperatorZip$Zip$InnerSubscriber.onNext(OperatorZip.java:330)
05-06 00:38:25.642 28106-28166/com.instano.buyer W/System.err﹕ ... 10 more
PS:Log.fatalError(err)
只是Android.util.Log.e(...)
修改
经过大量的反复试验,这对我来说变成了wont fix
。 zipWith(Observable.interval...)
似乎是罪魁祸首和可能的框架错误。删除这些行(以及我的周期性发射功能)我的代码可以工作。
我正在使用一个可能从不同线程调用onNext
的主题,然后我在它上面执行Obeservable运算符。
答案 0 :(得分:2)
我认为(但我不确定)问题是您的背压配置是在zip
运算符之后。
zip
运算符需要缓冲一个Observable
的项目以将其与另一个Observable
压缩。这是应该抛出异常的缓冲区。 (见here)
要解决您的问题,我认为您应该尝试在Observable
运算符中使用的zip
上添加背压配置。
示例:
obs.zipWith(Observable.interval(150, TimeUnit.MILLISECONDS).onBackPressureDrop());
obs.onBackPressureBlock().zipWith(Observable.interval(150, TimeUnit.MILLISECONDS));
答案 1 :(得分:2)
@dwursteisen和@zsxwing的答案是正确的。
区间运算符是基于时间发出的运算符,因此是&#34; hot&#34;并且不支持背压。因此,它将继续发出并填充zip的内部有界缓冲区,从而导致MissingBackpressureException。
处理&#34; hot&#34;源(例如基于时间或用户事件的源)必须选择如何处理溢出的策略。
在这种情况下,您需要将该策略放在interval
运算符上。
以下代码显示了正在进行的操作以及处理它的选项:
import java.util.concurrent.TimeUnit;
import rx.Observable;
public class ZipInterval {
public static void main(String... args) {
Observable<Long> slowHotSource = Observable.interval(1, TimeUnit.SECONDS);
/** This one is fast and hot so will cause a MissingBackpressureException.
*
* This is because a "hot" source based on time does not obey backpressure
* and keeps emitting regardless of what the downstream asks for.
*
* Examples of "hot" and "cold" and approaches to both can be found at:
* https://speakerdeck.com/benjchristensen/reactive-programming-with-rx-at-qconsf-2014?slide=90 and
* https://github.com/ReactiveX/RxJava/wiki/Backpressure
* */
// Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS);
/**
* The following version of 'fastHotSource' composes a simple flow control strategy.
*/
Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS).onBackpressureDrop();
Observable<String> zipped = Observable.zip(slowHotSource, fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- zip output");
zipped.take(10).toBlocking().forEach(System.out::println);
/**
* The outcome of the above is probably not what is expected though.
*
* This is because zip will buffer the output and then `fastHotSource` will drop until
* the zip buffer asks for more.
*
* For temporal or "hot" sources like this, using `withLatestFrom` or `combineLatest`
* is often more appropriate than `zip`.
*/
Observable<String> latest = slowHotSource.withLatestFrom(fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- latest output");
latest.take(10).toBlocking().forEach(System.out::println);
}
}
这个输出是:
---- zip output
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
---- latest output
0 1002
1 2002
2 3000
3 4001
4 5003
5 6001
6 7000
7 8002
8 9005
9 10000
答案 2 :(得分:0)
尝试使用combineLatest
,因为组合lastest不会等待新值调用onNext,它会在新值到达函数时使用最新值