Reactor 3 学习笔记(1)

Reactor 3 与之前学习的RxJava是同一类(反应式编程)框架,基本概念大致差不多,简单记录一下:

Reactor 3 利用了java 8中的CompletableFuture、Stream、Duration,在此基础上发展出了二个更通用的模型:Flux及Mono.

一、Flux

Flux 简单点讲,就是一个可以发射1到N个元素的异步"发射器",官方给的示例图如下:

1,2,3...这些颜色各异的小圆,代表正常发射出来的数据;(对应onNext方法)

上右黑色的竖线表示发送完成;(对应onComplete方法)

如果发射过程中出现异常,竖线用大红叉叉表示;(对应onError方法)

 

二、Mono

相对Flux而言,Mono最多只能发射1个元素,示例图如下:

 

三、Gradle依赖

 

四、常用方法

4.1 、just/fromArray/range

点击just可以看到源码:

注意:注释中给了一个图片地址 https://raw.githubusercontent.com/reactor/reactor-core/v3.1.3.RELEASE/src/docs/marble/justn.png

 

从图上看,就是发射一串数据。最终的输出也是如此:

1
A
3

其它类似的方法还有:fromArray、fromIterable、range 大家可以自行尝试。 

 

4.2、interval

1
2
3
4
5
6
7
8
@Test
public void fluxIntervalTest() throws InterruptedException {
    Flux.interval(Duration.of(500, ChronoUnit.MILLIS)).subscribe(System.out::println);
 
    //防止程序过早退出,放一个CountDownLatch拦住
    CountDownLatch latch = new CountDownLatch(1);
    latch.await();
}

顾名思义就是每隔一定时间,发射一个数据(从0开始),上面的示例表示每隔500毫秒,从0开始递增,发射1个数字,输出如下:

1
2
3
4
5
0
1
2
3
...

  

4.3、empty/never/error

empty方法几乎啥都不干,就发一个结束消息完事,示意图如下:

empty源码如下:

1
2
3
public static <T> Flux<T> empty() {
    return FluxEmpty.instance();
}

与之接近的,还有never方法

二者区别在于:empty里面至少还有一个结束消息,而never则是真的啥都没有。

还有一个比较特别的方法:error,只包含一个错误消息

示例代码如下:

1
Flux.error(new Exception("a wo,something is wrong!")).subscribe(System.out::println);

  

4.4、 generate/create

前面的几个方法,开发者不用显式的调用complete,而generate则需要调用,否则序列就不会终止。

输出如下:

1
2
3
4
5
6
7
8
9
10
11
AAAAA
85
80
32
19
90
72
0
37
46
33

注:generate中next只能调1次,否则会报错 reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalStateException: More than one call to onNext

create方法则没有next的调用次数限制,见下面的代码:

  

4.5、buffer/bufferTimeout/window/windowTimeout

字面意思理解,buffer指flux产生的数据,先缓冲起来,等缓冲区满了以后,才真正发射,所以上面的代码,第1段的意思是,0-9这10个数字,每次缓存3个,等3个数攒齐后,才输出。

而另一个版本bufferTimeout则不是根据元素的个数来缓冲,而是根据时间,第2段代码的意思是:flux每隔1秒,产生1个递增数字,而缓冲区每2秒才算充满,相当于每凑足2个数字后,才输出。

1
2
3
4
5
6
7
8
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9]
--------------
[0, 1]
[2, 3]
[4, 5]

 buffer示例图如下:

 

bufferTimeout示例图如下:

 

另外还有二个接近的方法window/windowTimeout,只是window/windowTimeout调用后的结果是Flux<Flux<T>>,处理过程中产生的流为UnicastProcessor对象。

window示意图:

windowTimeout示意图:

 

4.6、filter

输出:

1
2
3
4
5
0
2
4
6
8

 示意图:

 

4.7 zipWith

1
2
3
4
@Test
public void fluxZipTest() {
    Flux.just("A", "B").zipWith(Flux.just("1", "2", "3")).subscribe(System.out::println);
}

  

就是把各组元素,按位组合(就算用拉链袋封起来一样,因此得名),注意:这里有一个木桶原则,即 元素最少的"组",决定了最后输出的"组"个数。

上面代码的输出为:

1
2
[A,1]
[B,2]

  

4.8 take/takeLast/takeWhile/takeUntil

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void fluxTakeTest() {
    Flux.range(1, 10).take(3).subscribe(System.out::println);
    System.out.println("--------------");
    Flux.range(1, 10).takeLast(3).subscribe(System.out::println);
    System.out.println("--------------");
    Flux.range(1, 10).takeWhile(c -> c > 1 && c < 5).subscribe(System.out::println);
    System.out.println("--------------");
    Flux.range(1, 10).takeUntil(c -> c > 1 && c < 5).subscribe(System.out::println);
    System.out.println("--------------");
    Flux.range(1, 4).takeUntilOther(Flux.never()).subscribe(System.out::println);
}

take与takeLast很好理解,就是前n个或后n个。 takeWhile与takeUntil 需要记忆一下:

takeWhile 是先判断条件是否成立,然后再决定是否取元素(换言之,如果一开始条件不成立,就直接终止了);

takeUntil 是先取元素,直到遇到条件成立,才停下

takeUntilOther 则是先取元素,直到别一个Flux序列产生元素

所以上面的输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
--------------
8
9
10
--------------
--------------
1
2
--------------
1
2
3
4

注意:takeWhile无输出,因为判断条件一开始就不成立,直接cancel了;而takeUntilOther由于另一个flux使用了never()相当于没有任何元素,所以把前1个序列的元素取完,自然结束。 

takeWhile的示意图如下:

takeUntil的示意图如下:

takeUntilOther的示意图如下:

reactor的东西比较多,剩下的写到下篇

 

参考文章:

posted @   菩提树下的杨过  阅读(8505)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!
历史上的今天:
2014-08-12 ehcache2.8.3入门示例:hello world
点击右上角即可分享
微信分享提示