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依赖
apply plugin: 'java'
apply plugin: 'idea' repositories {
maven {
url "http://maven.aliyun.com/nexus/content/groups/public/"
}
mavenCentral()
jcenter()
} dependencies {
compile 'io.projectreactor:reactor-core:3.1.6.RELEASE'
testCompile('io.projectreactor:reactor-test:3.1.6.RELEASE')
testCompile('junit:junit:4.8.2')
}
四、常用方法
4.1 、just/fromArray/range
import org.junit.Test;
import reactor.core.publisher.Flux; public class FluxTest { @Test
public void fluxJustTest() {
Flux.just("1", "A", 3).subscribe(System.out::println);
}
}
点击just可以看到源码:
/**
* Create a {@link Flux} that emits the provided elements and then completes.
* <p>
* <img class="marble" src="https://raw.githubusercontent.com/reactor/reactor-core/v3.1.3.RELEASE/src/docs/marble/justn.png" alt="">
* <p>
* @param data the elements to emit, as a vararg
* @param <T> the emitted data type
*
* @return a new {@link Flux}
*/
@SafeVarargs
public static <T> Flux<T> just(T... data) {
return fromArray(data);
}
注意:注释中给了一个图片地址 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
@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个数字,输出如下:
0
1
2
3
...
4.3、empty/never/error
@Test
public void fluxEmptyTest() {
Flux.empty().subscribe(System.out::println);
}
empty方法几乎啥都不干,就发一个结束消息完事,示意图如下:

empty源码如下:
public static <T> Flux<T> empty() {
return FluxEmpty.instance();
}
与之接近的,还有never方法
public static <T> Flux<T> never() {
return FluxNever.instance();
}
二者区别在于:empty里面至少还有一个结束消息,而never则是真的啥都没有。
还有一个比较特别的方法:error,只包含一个错误消息

示例代码如下:
Flux.error(new Exception("a wo,something is wrong!")).subscribe(System.out::println);
4.4、 generate/create
前面的几个方法,开发者不用显式的调用complete,而generate则需要调用,否则序列就不会终止。
@Test
public void fluxGenerateTest() {
Flux.generate(i -> {
i.next("AAAAA");
//i.next("BBBBB");//注意generate中next只能调用1次
i.complete();
}).subscribe(System.out::println); final Random rnd = new Random();
Flux.generate(ArrayList::new, (list, item) -> {
Integer value = rnd.nextInt(100);
list.add(value);
item.next(value);
if (list.size() >= 10) {
item.complete();
}
return list;
}).subscribe(System.out::println);
}
输出如下:
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的调用次数限制,见下面的代码:
@Test
public void fluxCreateTest() {
Flux.create(i -> {
i.next("A");
i.next("B");
i.complete();
}).subscribe(System.out::println); final Random rnd = new Random();
Flux.create(item -> {
for (int i = 0; i < 10; i++) {
item.next(i);
}
}).subscribe(System.out::println);
}
4.5、buffer/bufferTimeout/window/windowTimeout
@Test
public void fluxBufferTest() throws InterruptedException {
Flux.range(0, 10).buffer(3).subscribe(System.out::println); System.out.println("--------------"); Flux.interval(Duration.of(1, ChronoUnit.SECONDS))
.bufferTimeout(2, Duration.of(2, ChronoUnit.SECONDS))
.subscribe(System.out::println); //防止程序过早退出,放一个CountDownLatch拦住
CountDownLatch latch = new CountDownLatch(1);
latch.await();
}
字面意思理解,buffer指flux产生的数据,先缓冲起来,等缓冲区满了以后,才真正发射,所以上面的代码,第1段的意思是,0-9这10个数字,每次缓存3个,等3个数攒齐后,才输出。
而另一个版本bufferTimeout则不是根据元素的个数来缓冲,而是根据时间,第2段代码的意思是:flux每隔1秒,产生1个递增数字,而缓冲区每2秒才算充满,相当于每凑足2个数字后,才输出。
[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
@Test
public void fluxFilterTest() {
Flux.range(0, 10).filter(c -> c % 2 == 0).subscribe(System.out::println);
}
输出:
0
2
4
6
8
示意图:

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

就是把各组元素,按位组合(就算用拉链袋封起来一样,因此得名),注意:这里有一个木桶原则,即 元素最少的"组",决定了最后输出的"组"个数。
上面代码的输出为:
[A,1]
[B,2]
4.8 take/takeLast/takeWhile/takeUntil
@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
--------------
8
9
10
--------------
--------------
1
2
--------------
1
2
3
4
注意:takeWhile无输出,因为判断条件一开始就不成立,直接cancel了;而takeUntilOther由于另一个flux使用了never()相当于没有任何元素,所以把前1个序列的元素取完,自然结束。
takeWhile的示意图如下:

takeUntil的示意图如下:

takeUntilOther的示意图如下:

reactor的东西比较多,剩下的写到下篇吧
参考文章:
Reactor 3 学习笔记(1)的更多相关文章
- Reactor 3 学习笔记(2)
接上篇继续学习各种方法: 4.9.reduce/reduceWith @Test public void reduceTest() { Flux.range(1, 10).reduce((x, y) ...
- muduo学习笔记(二)Reactor关键结构
目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...
- Mudo C++网络库第六章学习笔记
muduo网络库简介 高级语言(Java, Python等)的Sockects库并没有对Sockects API提供更高层的封装, 直接用它编写程序很容易掉到陷阱中: 网络库的价值还在于能方便地处理并 ...
- Netty 学习笔记(1)通信原理
前言 本文主要从 select 和 epoll 系统调用入手,来打开 Netty 的大门,从认识 Netty 的基础原理 —— I/O 多路复用模型开始. Netty 的通信原理 Netty 底层 ...
- muduo网络库学习笔记(三)TimerQueue定时器队列
目录 muduo网络库学习笔记(三)TimerQueue定时器队列 Linux中的时间函数 timerfd简单使用介绍 timerfd示例 muduo中对timerfd的封装 TimerQueue的结 ...
- Netty学习笔记(二)——netty组件及其用法
1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...
- 《精通并发与Netty》学习笔记(01 - netty介绍及环境搭建)
一.Netty介绍 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. ...
- Netty学习笔记-入门版
目录 Netty学习笔记 前言 什么是Netty IO基础 概念说明 IO简单介绍 用户空间与内核空间 进程(Process) 线程(thread) 程序和进程 进程切换 进程阻塞 文件描述符 文件句 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
随机推荐
- Ex 5_26 变量约束是否能同时满足(并查集)_第九次作业
利用并查集进行处理,定义一个维护数组components,components[i]表示变量序号为i的变量所处的集合,首先处理相等的变量,把它们放入同一个集合中,最后再处理不相等变量,若两个不相等的变 ...
- GitHub学习一-本地电脑与GitHub绑定
1.创建ssh key $ ssh-keygen -t rsa -C "your_email@youremail.com"安装完git,右键git bash here,创建ssh ...
- 读取本地图片 BitmapImage
BitmapImage defImage = new BitmapImage(); defImage.BeginInit(); defImage.UriSource = new Uri(@" ...
- html 页内跳转
第一种 <a href="#div1">to div1</a> //跳转链接<div id="div1">div1</ ...
- 《剑指offer》-前n项和不准用通解和各种判断
题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 这题目简直没事找事...为啥这么说,因为没有限 ...
- jQuery插件实践之轮播练习(一)
所有文章搬运自我的个人主页:sheilasun.me 因为从来没写过jQuery插件,所以本文要通过一个轮播的例子,练习jQuery插件的写法. 新建插件文件 在讨论细节之前,先新建插件文件(当然也可 ...
- #10 [AH2017/HNOI2017]大佬
题解: 题意看上去挺复杂的 分析一下就能发现自己的自信是没啥用的 只要随便dp一下看看最多能有多少天不使用增加自信 然后问题就变成了 求C1+C2+k=C 然后发现C有10^8 显然枚举C1是不行的了 ...
- k8s 关键字以及管理流程。
一.流程图如下 二.用户通过kubectl提交需要运行的docker container(pod). 三.api server把请求存储在etcd里面. 四.scheduler(调度)扫描,分配机器. ...
- BZOJ3064 Tyvj 1518 CPU监控 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3064 题意概括 一个序列,要你支持以下操作: 1. 区间询问最大值 2. 区间询问历史最大值 3. ...
- word 中如何取消格式标记
开始菜单栏下: 或者: