RxJava中真实背压的最佳实现
RxJava中的背压不是真正的背压,只是忽略了一些元素集 但如果我不能释放任何元素,我需要以某种方式减缓发射呢 RxJava不能影响元素的发射,所以开发人员需要自己实现它。但是怎么做呢 想到的最简单的方法是使用一些计数器,发射时递增,完成时递减 就像这样:RxJava中真实背压的最佳实现,java,multithreading,rx-java,reactive-programming,Java,Multithreading,Rx Java,Reactive Programming,RxJava中的背压不是真正的背压,只是忽略了一些元素集 但如果我不能释放任何元素,我需要以某种方式减缓发射呢 RxJava不能影响元素的发射,所以开发人员需要自己实现它。但是怎么做呢 想到的最简单的方法是使用一些计数器,发射时递增,完成时递减 就像这样: public static void sleep(int ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { e.p
public static void sleep(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
AtomicInteger counter = new AtomicInteger();
Scheduler sA = Schedulers.from(Executors.newFixedThreadPool(1));
Scheduler sB = Schedulers.from(Executors.newFixedThreadPool(5));
Observable.create(s -> {
while (!s.isUnsubscribed()) {
if (counter.get() < 100) {
s.onNext(Math.random());
counter.incrementAndGet();
} else {
sleep(100);
}
}
}).subscribeOn(sA)
.flatMap(r ->
Observable.just(r)
.subscribeOn(sB)
.doOnNext(x -> sleep(1000))
.doOnNext(x -> counter.decrementAndGet())
)
.subscribe();
}
公共静态无效睡眠(int-ms){
试一试{
睡眠(ms);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args)引发InterruptedException{
AtomicInteger计数器=新的AtomicInteger();
Scheduler sA=Schedulers.from(Executors.newFixedThreadPool(1));
Scheduler sB=Schedulers.from(Executors.newFixedThreadPool(5));
可观察。创建(s->{
而(!s.isUnsubscribed()){
if(counter.get()<100){
s、 onNext(Math.random());
counter.incrementAndGet();
}否则{
睡眠(100);
}
}
}).subscribeOn(sA)
.flatMap(r->
可观测的。仅(r)
(某人)
.doOnNext(x->睡眠(1000))
.doOnNext(x->counter.decrementAndGet())
)
.subscribe();
}
但我觉得这条路很差。有更好的解决方案吗?正如您自己所指出的,这实际上与RxJava无关。
如果您最终必须处理所有事件,但希望以自己的速度处理,请使用队列:
ExecutorService emiter = Executors.newSingleThreadExecutor();
ScheduledExecutorService workers = Executors.newScheduledThreadPool(4);
BlockingQueue<String> events = new LinkedBlockingQueue<>();
emiter.submit(() -> {
System.out.println("I'll send 100 events as fast as I can");
for (int i = 0; i < 100; i++) {
try {
events.put(UUID.randomUUID().toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
workers.scheduleWithFixedDelay(
() -> {
String result = null;
try {
result = events.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("I don't care, got %s only now", result));
}, 0, 1, TimeUnit.SECONDS
);
ExecutorService emitter=Executors.newSingleThreadExecutor();
ScheduledExecutorService workers=执行者。newScheduledThreadPool(4);
BlockingQueue事件=新建LinkedBlockingQueue();
emitter.submit(()->{
System.out.println(“我会尽快发送100个事件”);
对于(int i=0;i<100;i++){
试一试{
events.put(UUID.randomuid().toString());
}捕捉(中断异常e){
e、 printStackTrace();
}
}
});
workers.Schedule带有固定的延迟(
() -> {
字符串结果=null;
试一试{
结果=events.take();
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.println(String.format(“我不在乎,现在才得到%s”,result));
},0,1,时间单位为秒
);
RxJava中的背压不是真正的背压
RxJava的背压实现是后续生产者和消费者之间通过请求通道进行的无阻塞合作。消费者通过request()
请求一定数量的元素,而生产者通过onNext
创建/生成/发出最多该数量的元素,有时在onNext
之间会有延迟
但只忽略某些元素集
只有当您显式地告诉RxJava删除任何溢出时,才会发生这种情况
RxJava不能影响元素的发射,所以开发人员需要自己实现它。但是怎么做呢
使用Observable.create
需要了解如何实现无阻塞背压,实际上不建议图书馆用户使用。RxJava有很多方法可以为您提供支持背压的流,而不会带来复杂性:
Observable.range(1, 100)
.map(v -> Math.random())
.subscribeOn(sA)
.flatMap(v ->
Observable.just(v).subscribeOn(sB)
.doOnNext(x -> sleep(1000))
)
.subscribe();
或
排队不是背压。背压的作用是向生产者发出信号,以减缓排放。这可能并不总是可能的,但在绝大多数情况下,这是可能的。这就是为什么JDK9中新的反应流规范中有明确的背压。我读过关于背压的话题。在我的例子中,我想问一种减缓元素发射的方法。假设我用游标从数据库中读取记录,我需要减慢它的速度,因为系统处理记录的速度比生产者发出记录的速度慢。这是基于拉动的,您可以尽可能快地拉动下游的记录。
Observable.create(SyncOnSubscribe.createStateless(
o -> o.onNext(Math.random())
)
.subscribeOn(sA)
...