为什么';使用observeOn时,我的RxJava可流动部件是否会尊重背压?
我正在尝试创建一个为什么';使用observeOn时,我的RxJava可流动部件是否会尊重背压?,java,multithreading,rx-java,reactivex,Java,Multithreading,Rx Java,Reactivex,我正在尝试创建一个可流动的,它发出关于反压力的事件,以避免内存问题,同时并行运行转换的每个阶段以提高效率。我已经创建了一个简单的测试程序来解释我的程序的不同步骤的行为,以及何时发出事件,何时等待不同的阶段 我的计划如下: public static void main(String[] args) throws ExecutionException, InterruptedException { Stream<Integer> ints = IntStream.range(0,
可流动的
,它发出关于反压力的事件,以避免内存问题,同时并行运行转换的每个阶段以提高效率。我已经创建了一个简单的测试程序来解释我的程序的不同步骤的行为,以及何时发出事件,何时等待不同的阶段
我的计划如下:
public static void main(String[] args) throws ExecutionException, InterruptedException {
Stream<Integer> ints = IntStream.range(0, 1000).boxed().collect(Collectors.toList())
.stream().map(i -> {
System.out.println("emitting:" + i);
return i;
});
Flowable<Integer> flowable = Flowable.fromIterable(() -> ints.iterator());
System.out.println(String.format("Buffer size: %d", flowable.bufferSize()));
Long count = flowable.onBackpressureBuffer(10)
.buffer(10)
.flatMap(buf -> {
System.out.println("Sleeping 500 for batch");
Thread.sleep(500);
System.out.println("Got batch of events");
return Flowable.fromIterable(buf);
}, 1)
.map(x -> x + 1)
.doOnNext(i -> {
System.out.println(String.format("Sleeping : %d", i));
Thread.sleep(100);
System.out.println(i);
})
.count()
.blockingGet();
System.out.println("count: " + count);
}
但是,如果我试图通过添加一些对.observeOn(Schedulers.computation())
的调用来并行化不同的操作阶段,那么我的程序似乎不再考虑反压力。我的代码现在看起来像:
public static void main(String[] args) throws ExecutionException, InterruptedException {
Stream<Integer> ints = IntStream.range(0, 1000).boxed().collect(Collectors.toList())
.stream().map(i -> {
System.out.println("emitting:" + i);
return i;
});
Flowable<Integer> flowable = Flowable.fromIterable(() -> ints.iterator());
System.out.println(String.format("Buffer size: %d", flowable.bufferSize()));
Long count = flowable.onBackpressureBuffer(10)
.buffer(10)
.observeOn(Schedulers.computation())
.flatMap(buf -> {
System.out.println("Sleeping 500 for batch");
Thread.sleep(500);
System.out.println("Got batch of events");
return Flowable.fromIterable(buf);
}, 1)
.map(x -> x + 1)
.observeOn(Schedulers.computation())
.doOnNext(i -> {
System.out.println(String.format("Sleeping : %d", i));
Thread.sleep(100);
System.out.println(i);
})
.observeOn(Schedulers.computation())
.count()
.blockingGet();
System.out.println("count: " + count);
}
假设我的批处理阶段正在调用外部服务,但由于延迟,我希望它们并行运行。我还希望在给定的时间控制内存中的项目数量,因为最初发出的项目数量可能是高度可变的,并且在批处理上运行的阶段比事件的初始发出慢得多
如何使我的可流动
在计划程序
中尊重背压?为什么我在调用observeOn
时似乎只不尊重背压
如何让我的可流动尊重背压通过调度程序
实际上,施加on背压buffer
会使其上方的源与下游施加的任何背压断开,因为它是一个无界in操作符。您不需要它,因为Flowable.fromIterable
(顺便说一句,RxJava有一个范围
操作符)支持并尊重背压
为什么当我打电话给observeOn时,似乎只是不尊重背压
在第一个示例中,出现了一种称为调用堆栈阻塞的自然背压。RxJava在默认情况下是同步的,大多数操作符不引入异步,就像第一个示例中没有引入异步一样
observeOn
引入了异步边界,因此在理论上,各阶段可以彼此并行运行。它有一个默认的128元素预取缓冲区,可以通过它的一个重载进行调整。然而,在您的情况下,缓冲区(10)实际上会将预取量放大到1280,这可能仍然会导致一次性完全消耗1000个元素长的源。为什么buffer(10)
会将预取量放大到bufferSize*flowablePrefetchBufferSize
?确实,如果我将其更改为发射10000个整数,而不是在第1280个整数之后,我可以看到它由于背压而停止发射,但是,我该如何收集成批的东西发送给外部服务,而不爆炸我在内存中保存的项目数量呢?因为buffer
知道,当它收到对N个列表的请求时,它必须从其上游请求10*N个元素来满足该需求。正如我提到的,您可以参数化observeOn
,以减少请求。
public static void main(String[] args) throws ExecutionException, InterruptedException {
Stream<Integer> ints = IntStream.range(0, 1000).boxed().collect(Collectors.toList())
.stream().map(i -> {
System.out.println("emitting:" + i);
return i;
});
Flowable<Integer> flowable = Flowable.fromIterable(() -> ints.iterator());
System.out.println(String.format("Buffer size: %d", flowable.bufferSize()));
Long count = flowable.onBackpressureBuffer(10)
.buffer(10)
.observeOn(Schedulers.computation())
.flatMap(buf -> {
System.out.println("Sleeping 500 for batch");
Thread.sleep(500);
System.out.println("Got batch of events");
return Flowable.fromIterable(buf);
}, 1)
.map(x -> x + 1)
.observeOn(Schedulers.computation())
.doOnNext(i -> {
System.out.println(String.format("Sleeping : %d", i));
Thread.sleep(100);
System.out.println(i);
})
.observeOn(Schedulers.computation())
.count()
.blockingGet();
System.out.println("count: " + count);
}
Buffer size: 128
emitting:0
emitting:1
emitting:2
emitting:3
emitting:4
emitting:5
emitting:6
emitting:7
emitting:8
emitting:9
emitting:10
Sleeping 500 for batch
emitting:11
emitting:12
... everything else is emitted here ...
emitting:998
emitting:999
Got batch of events
Sleeping 500 for batch
Sleeping : 1
1
Sleeping : 2
2
Sleeping : 3
3
Sleeping : 4
4
Sleeping : 5
Got batch of events
Sleeping 500 for batch
5
Sleeping : 6
6
Sleeping : 7
7
Sleeping : 8
8
Sleeping : 9
9
Sleeping : 10
Got batch of events
Sleeping 500 for batch
10
Sleeping : 11
11
Sleeping : 12
12
Sleeping : 13
13
Sleeping : 14
14
Sleeping : 15
Got batch of events
Sleeping 500 for batch
15
Sleeping : 16
16
Sleeping : 17
17
Sleeping : 18
18
Sleeping : 19
19
Sleeping : 20
Got batch of events
Sleeping 500 for batch
20
Sleeping : 21
21
Sleeping : 22
22
Sleeping : 23
23
Sleeping : 24
24
Sleeping : 25
Got batch of events
Sleeping 500 for batch
25