Reactor3 源码解析二十一: FluxMerge源码剖析

本文深入解析Reactor3中的FluxMerge操作,对比了merge和mergeSequential两种合并策略。merge按照元素实际产生顺序合并多个源,呈现交叉输出效果,利用内部队列和WIP确保线程安全。而mergeSequential则按源订阅顺序逐个消费源序列,确保先订阅的源完全消费完毕后才处理下一个源,适合需要保持源顺序的场景。
摘要由CSDN通过智能技术生成

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值