我已经在RxJava上阅读了一些关于背压的文档,但是我无法找到一个详细的解释,比如它是如何在图书馆内部发生的,每个人都只是总结它,就像“生产者”太快,“消费者”太慢。
例如,如下面的代码:
Observable.interval(1, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.newThread())
.subscribe(
i -> {
System.out.println(i);
try {
Thread.sleep(100);
} catch (Exception e) { }
},
System.out::println);
我一直在浏览RxJava源代码,所以我的理解是在主线程中我们将在每毫秒发出事件,一旦我们发出它,我们将值传递给System.out.println(i)方法并抛出它进入newThead调度程序的线程池并在runnable中运行该方法。
所以我的问题是,异常是如何在内部发生的?因为当我们调用Thread.sleep()时,我们正在睡觉处理方法调用的线程 - > System.out.println()没有影响线程池中的其他线程,怎么会导致异常。是因为线程池不再具有足够的可用线程了吗?
由于
答案 0 :(得分:6)
您可以将背压视为允许一个操作员向其上游来源发出许可证的系统:您可以给我128个元素。稍后这个操作员可能会说"好吧,给我另一个96"所以总共可能有224份许可证。某些来源,例如interval
并不关心许可,只是定期发布价值。由于许可证的数量通常与队列或缓冲区中的可用容量密切相关,因此分发超过这些存储的容量可以保持MissingBackpressureException
。
检测背压违规主要发生在有界队列的offer
返回false时,例如observeOn
中指示队列已满的那个。
检测违规行为的第二种方法是跟踪运营商中未完成的许可证计数,例如onBackpressureDrop
,每当上游发送的数量超过此数量时,运营商就不会转发它:
// in onBackpressureDrop
public void onNext(T value) {
if (emitted != availablePermits) {
emitted++;
child.onNext(value);
} else {
// ignoring this value
}
}
子订阅者通过request()发出通知,通常会导致onBackpressureDrop
中出现类似内容:
public void childRequested(long n) {
availablePermits += n;
}
实际上,由于可能的异步执行,availablePermits
是AtomicLong
(并称为requested
)。