Flux.just("a", "b", "c")
.log(null, Level.INFO,true) // line 18
.flatMap(value -> Mono.just(value.toUpperCase())
.publishOn(Schedulers.elastic()), 2)
.log(null, Level.INFO,true) // line 21
.subscribe();
部分输出:
13:03:46 [main] INFO - | request(2) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(a) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(b) Flux.log(App.java:18)
13:03:46 [elastic-2] INFO - onNext(A) Flux.log(App.java:21)
13:03:46 [elastic-2] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(c) Flux.log(App.java:18)
13:03:46 [elastic-3] INFO - onNext(B) Flux.log(App.java:21)
13:03:46 [elastic-3] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [elastic-2] INFO - onNext(C) Flux.log(App.java:21)
13:03:46 [elastic-2] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [main] INFO - | onComplete() Flux.log(App.java:18)
13:03:46 [main] INFO - onComplete() Flux.log(App.java:21)
问题:
为什么flatMap
要求main
线程中有2个元素,然后从其他线程中请求更多元素?
为什么subscribe
线程没有处理main
?
答案 0 :(得分:1)
第一个Subscription.request
金额取决于您指定的并发级别2
。由于您在主线程中调用.subscribe
,因此将在该线程上准确调用第一个prefetch
请求。
让我们来看看下一个架构:
.subscribe()[Thread main]
- > FluxLog.source.subscribe()[Tread Main]
- > FluxFlatMap.source.subscribe()[ThreadMain]
- > FluxJust.subscriber.onSubscribe()
- > FluxFlatMap.subscription.request(concurrency)[Thread Main]
然后,从那一点开始将是硬核:)。由于您的内部流将由FlatMapInner
订阅,它将观察Scheduler.elastic
上的所有信号(onNext,onError,onComplete)(因为您的.publishOn
)。反过来,当内部流完成后,FlatMapInnner
上的onComplete
将通知主FlatMapMain
,它是整个flatMap
机制的驱动程序。 FlatMapInner
和FlatMapMain
之间的互动已超过FlatMapMain.innerComplete
。因为,从FlatMapMain的角度来看,内部FlatMapInner
扮演的角色是Queue
,所有元素都将是drained
。保持冷静,如果你不知道这里发生了什么,请不要惊慌。该方法的所有想法都是从内部流中排出数据并将其发送到下游,然后向上游请求新的数据部分。您应该记住的是innerComplete
从FlatMapInner.onComplete
调用并被移动到另一个调度程序,因此这意味着将从{{1}中指定的线程调用下一个Subscription.request
}
因此,示意性地说明该过程如下:
Mono.just(value.toUpperCase()).publishOn(Schedulers.elastic())
- > FluxFlatMap.FlatMapMain.onNext [Thread Main]
- > Publisher m = mapper(...)
- > m.subscribe(new FluxFlatMap.FlatMapInner())
- > FluxFlatMap.FlatMapInner.onNext("a") [Thread Elastic N]
- > LambdaSubscriber.onNext("c") [Thread Elastic N]
- > FluxFlatMap.FlatMapInner.onComplete() [Thread Elastic N]
- > FluxFlatMap.FlatMapMain.drainLoop() [Thread Elastic N]
- > FluxFlatMap.FlatMapMain.drainLoop() [Thread Elastic N] { ... subscription.request(amountOfCompletedInners)
- > .... FlatMap.FlatMapMain.onNext() [Thread Elastic N]
- > ....
因此,您将看到main上的第一个请求(2),然后是弹性请求(1)(因为一个内部已经完成,因此FlatMap将从上游请求另一个1元素以满足并发的要求)。