根据ReactiveX文档:
请注意,FlatMap合并了这些Observable的发射,因此 他们可能交错。
我试了一下,似乎遇到了一个问题。
请注意,11, 12, 13 and 14
一起在Scheduler.compute()
个线程上一起运行。然后15 and 21
在2秒后一起运行(预期,因为delayedIdentity(...)
函数中指定的延迟)。但是,所有后续运行都在前一次运行后2秒发生(参见第7-10行;数据22, 23, 24 and 25
)。我期望这最后4个交错,因为我使用了flatMap(...)
。似乎在使用flatMap时,它会等待元素的结果,然后继续执行下一个元素的结果,从而阻止它进行交错。
我还使用了delayedEcho(...)
替代delayedIdentity(...)
,它也产生了非交错结果。
给出以下代码:
public class Main {
private static int i = 0;
public static void main(String[] args) throws InterruptedException {
System.out.println(MessageFormat.format("{0} {1} {2}", getLine(), Instant.now(), "Start"));
Arrays.asList(11, 12, 13, 14, 15)
.stream()
.map(n -> Observable.just(n))
.map(o -> o
.observeOn(Schedulers.computation())
.flatMap(Main::delayedIdentity)
.subscribe(Main::println))
.collect(Collectors.toSet());
Observable.just(21, 22, 23, 24, 25)
.observeOn(Schedulers.computation())
.flatMap(Main::delayedIdentity)
.subscribe(Main::println);
Thread.sleep(25 * 1000);
}
public static Observable<Integer> delayedIdentity(Integer n) {
return Observable.create(s -> {
try {
Thread.sleep(2 * 1000);
s.onNext(n);
s.onCompleted();
} catch (InterruptedException e) {
s.onError(e);
}
});
}
public synchronized static void println(Object o) {
System.out.println(MessageFormat.format("{0} {1} {2}", getLine(), Instant.now(), o));
}
public synchronized static int getLine() {
return i++;
}
}
给出以下控制台日志:
0 2016-07-21T06:05:36.908Z Start
1 2016-07-21T06:05:39.169Z 11
2 2016-07-21T06:05:39.169Z 14
3 2016-07-21T06:05:39.169Z 12
4 2016-07-21T06:05:39.170Z 13
5 2016-07-21T06:05:41.171Z 15
6 2016-07-21T06:05:41.172Z 21
7 2016-07-21T06:05:43.175Z 22
8 2016-07-21T06:05:45.176Z 23
9 2016-07-21T06:05:47.180Z 24
10 2016-07-21T06:05:49.182Z 25
Process finished with exit code 0
Echo alternative:
public static Observable<Integer> delayedEcho(Integer n) {
return Observable.create(s -> {
try {
s.onNext(n);
Thread.sleep(2 * 1000);
s.onNext(n);
s.onCompleted();
} catch (InterruptedException e) {
s.onError(e);
}
});
}
这导致了以下类似的结果:
0 2016-07-21T06:13:19.867Z Start
1 2016-07-21T06:13:20.073Z 11
2 2016-07-21T06:13:20.074Z 14
3 2016-07-21T06:13:20.074Z 13
4 2016-07-21T06:13:20.075Z 12
5 2016-07-21T06:13:22.078Z 11
6 2016-07-21T06:13:22.079Z 12
7 2016-07-21T06:13:22.079Z 13
8 2016-07-21T06:13:22.080Z 14
9 2016-07-21T06:13:22.081Z 15
10 2016-07-21T06:13:22.081Z 21
11 2016-07-21T06:13:24.087Z 15
12 2016-07-21T06:13:24.087Z 21
13 2016-07-21T06:13:24.087Z 22
14 2016-07-21T06:13:26.089Z 22
15 2016-07-21T06:13:26.089Z 23
16 2016-07-21T06:13:28.091Z 23
17 2016-07-21T06:13:28.092Z 24
18 2016-07-21T06:13:30.094Z 24
19 2016-07-21T06:13:30.095Z 25
20 2016-07-21T06:13:32.098Z 25
Process finished with exit code 0
我做错了什么?
答案 0 :(得分:1)
为了确保你理解Schedulers.computation()
调度程序 - 它不是一个线程,它主要是像线程池。如果1个线程忙,它将返回你的新线程。要检查它,只需放置类似
System.out.println(MessageFormat.format("Thread id = {0}", Thread.currentThread().getId()));
在delayedIdentity
功能中。这个知识可能会更清楚。
我不是百分之百确定这里有什么令人困惑的,但我会尝试逐步解释结果。
Arrays.asList(11, 12, 13, 14, 15)
.stream()
.map(n -> Observable.just(n))
.map(o -> o
.observeOn(Schedulers.computation())
.flatMap(Main::delayedIdentity)
.subscribe(Main::println))
.collect(Collectors.toSet());
因此,当您运行该代码时,来自流的所有数据都将转换为5 Observables
,然后,几乎在它们同时在延迟delayedIdentity
之后开始仅发出一个项目。结果你几乎可以同时在控制台中看到11, 12, 13, 14, 15
。它不应该保存订单,因为stream
可以传递无序状态。
因此,因为你在第一个语句中使用非主线程,所以第二个语句将在第一个
之后立即开始 Observable.just(21, 22, 23, 24, 25)
.observeOn(Schedulers.computation())
.flatMap(Main::delayedIdentity)
.subscribe(Main::println);
所以简单地说21,在delayedIdentity
几乎与11, 12, 13, 14, 15
同时等待2秒,然后在控制台中打印所有这个数字。 22, 23, 24, 25
- 将在一段一秒的时间内相互打印。
请问我是否不清楚。