其实有一个特别的例子是just
,直觉会认为just
就是产生一个publisher
等人来subscribe
,理所当然就是Cold Publisher,我一开始也是这样认为,直到看到官方doc说明他是Hot Publisher,原来最熟悉的好朋友其实如此的陌生,又在程序的道路上学习了人生的一课,Cold Publisher是Lazy loading,但其实just
在assembly time就已经准备好所有的data,当有Subscriber
订阅只是在replay一次而已。
使用Flux.just
的时候,在assembly time就已经取得资料,我们可以改成透过defer
,回归lazy,直到subscribe才会取资料,defer
就是延迟的意思,透过Supplier
来达到延迟的效果,来源资料会被延迟到subscribe才会被初始化,也是因为这样,如果来源资料是与当下时间有关,这样每个不同的subscribe都会取到不同的时间,但本质上还是一个Cold Publisher。
以下范例是分别透过just
& defer
来取用现在时间,可以看出just
每次subscribe结果会相同,就能得知just
在assembly time就已经取资料了,而defer
则是延迟直到subscribe才真的去取得现在时间,看到这边可以会有点错乱,原本以为Hot Publisher是每次结果会不相同,但这边的Hot Publisher是just
每次结果相同,COLD Publisher的defer
则会每次不同,老实说我是有点错乱,官方文件上也没有明确定义cold & hot,所以我个人认为是产生资料的时间点,如果是lazy的要等到subscribe才会触发的就是COLD Publisher,如果无论有没有subscribe都会先取得资料的,则是Hot Publisher。
Mono<Long> clock = Mono.just(System.currentTimeMillis());
Mono<Long> clockDefer = Mono.defer(() -> Mono.just(System.currentTimeMillis()));
Thread.sleep(500);
clock.subscribe(t -> System.out.println("clock:"+ t));
clockDefer.subscribe(t -> System.out.println("\tclockDefer:"+ t));
Thread.sleep(500);
clock.subscribe(t -> System.out.println("clock:"+ t));
clockDefer.subscribe(t -> System.out.println("\tclockDefer:"+ t));
/*
clock:1631980808996
clockDefer:1631980809602
clock:1631980808996
clockDefer:1631980810105 */
再比较一次COLD 与HOT的不同,第一个范例是先用fromIterable
产生一个cold publisher,两个Subscriber 得到的结果是一模一样的。
Flux<String> source =
Flux.fromIterable(Arrays.asList("blue", "green", "orange", "purple"))
.map(String::toUpperCase);
source.subscribe(d -> System.out.println("Subscriber 1: " + d));
source.subscribe(d -> System.out.println("Subscriber 2: " + d));
/*
Subscriber 1: BLUE
Subscriber 1: GREEN
Subscriber 1: ORANGE
Subscriber 1: PURPLE
Subscriber 2: BLUE
Subscriber 2: GREEN
Subscriber 2: ORANGE
Subscriber 2: PURPLE
*/
再来利用前面学到的Sinks
动态的产生Flux
,当时就有提到後面subscribe的只会得到之後的资料,可以看到Subscriber 2 就只有橘色与紫色。
Sinks.Many<String> hotSource = Sinks.unsafe().many().multicast().directBestEffort();
Flux<String> hotFlux = hotSource.asFlux().map(String::toUpperCase);
hotFlux.subscribe(d -> System.out.println("Subscriber 1 to Hot Source: "+d));
hotSource.emitNext("blue", FAIL_FAST);
hotSource.tryEmitNext("green").orThrow();
hotFlux.subscribe(d -> System.out.println("Subscriber 2 to Hot Source: "+d));
hotSource.emitNext("orange", FAIL_FAST);
hotSource.emitNext("purple", FAIL_FAST);
hotSource.emitComplete(FAIL_FAST);
/*
Subscriber 1 to Hot Source: BLUE
Subscriber 1 to Hot Source: GREEN
Subscriber 1 to Hot Source: ORANGE
Subscriber 2 to Hot Source: ORANGE
Subscriber 1 to Hot Source: PURPLE
Subscriber 2 to Hot Source: PURPLE
*/
经过两天的学习,应该能大致了解cold/hot publihser,不过其实官方文件并没有明确定义,所以建议也不用太钻牛角尖的想去定义每一个operator是属於哪一种,遇到再来讨论。
>>: @Day29 | C# WixToolset + WPF 帅到不行的安装包 [如何拿已经安装好的资料]
本系列文之後也会置於个人网站 在这之前,都是先请大家照着做,没有好好说明关於Keycloak的使用...
参考资料: Alex老师教学 PJCHENder笔记 卷动出现图片。 题目预设的过滤效果,避免多次触...
SphereFace 在2017年发表在CVPR的文章,改进原先使用softmax作为loss fu...
昨天原本要连同 Confirm buttom 一起讲的~,但平均一下每天的文章量,今天再接着讲另一个...
该文章同步发布於:我的部落格 还记得我们使用 let 方法来实作一个物件来让我们可以快速使用! 但...