Flux的buffer、window、groupBy主要是针对源序列进行拆分,将元素分配到不同的容器或group中,进行批处理。而merge和mergeSequential操作是将多个源合并成一个Flux源。merge操作按照所有源中元素的实际产生顺序进行合并,而mergeSequential操作则按照所有源被订阅的顺序 ,以源为单位进行合并。
Flux.merge(Flux.interval(Duration.ZERO, Duration.ofMillis(100)).take(5),
Flux.interval(Duration.ofMillis(50), Duration.ofMillis(100)).take(5))
.subscribe((t) -> System.out.println("Flux.merge :" + t + Thread.currentThread().getName()));
Thread.sleep(2000l);
输出结果
Flux.merge :0parallel-1
Flux.merge :0parallel-2
Flux.merge :1parallel-1
Flux.merge :1parallel-2
Flux.merge :2parallel-1
Flux.merge :2parallel-2
Flux.merge :3parallel-1
Flux.merge :3parallel-2
Flux.merge :4parallel-1
Flux.merge :4parallel-2
可以看出元素是交叉输出。实现原理,在FluxMerge.subscribe(LambdaSubscriber)的过程中, 两个FluxTake(FlutInterval)分别订阅FluxFlatMap#FlatMapInner,FlatMapInner内部维持一个queue,FluxInterval发射元素,在无并发的情况下,FlatMapMain#tryEmit直接将元素向下游传递,存在并发时则将元素暂存到对应的FlatMapInner的queue, 同时在FlatMapMain#drain中通过WIP保证只有一个线程从所有的queue中拉取元素并向下游传递消费。(FlatMapInner中使用的queue是spsc,所以必须保证单生产者单消费者)
FlatMapInner#onNext
public void onNext(R t) {
if (sourceMode == Fuseable.ASYNC) {
parent.drain(t);
}
else {
if (done) {
Operators.onNextDropped(t, parent.currentContext());
return;
}
if (s == Operators.cancelledSubscription()) {
Operators.onDiscard(t, parent.currentContext());
return;
}
//将元素交给FlatMapMain#tryEmit处理
parent.tryEmit(this, t);
}
}
FlatMapMain#tryEmit