以下为近期学习Reactor的一些见解,由于仍在入门阶段,所以所述难免有所偏颇,欢迎大家讨论和指教
为什么使用Reactor?
阻塞模式的弊端
阻塞就意味着程序将会空占系统的资源,是对资源的极大浪费,无法更好发挥硬件的性能。
HttpClient client = HttpClients.createDefault();
HttpGet request = new HttpGet("https://www.baidu.com");
HttpResponse response = client.execute(request);
例如上述代码段,在client.execute(request)执行时,程序就会陷入阻塞, 这时候当前程序占用的资源依旧会被占用,这势必浪费了大量资源。
常见异步模式实现
- Callback:即回调,当程序满足某一条件时,将会触发该方法。
- Futures:通过异步方法,获取一个Futures,当异步执行完后将会返回一个T,然而其返回的值并不是立刻有效。
- 以上两种方式不但api繁琐,而且很难配合使用。
Reactor的优势
- Reactor为非阻塞模式,避免了阻塞模式下对系统资源的占用;
- 响应式模式,当接受到结果后才会返回, 不存在类似于Futures返回无效结果的情况;
- 采用链式编程,简化了编码。
核心组件
Mono & Flux
Mono接收了0/1个响应结果
Flux是接收了0-n个响应结果的序列
如何创建Mono
Mono.just(1);
Mono.empty();
//相当于throw new Throwable("error message");
Mono.error(new Throwable("error message"));
如何创建Flux
Flux.range(1,6);
Flux.fromArray(new Integer[]{1,2,3});
Flux.fromStream(Stream.of(1,2,3));
互相转化
Flux → Mono
Mono<List<Integer>> mono = Flux.range(1, 5).collectList();
Mono→Flux
Flux<Integer> flux = Mono.just(1).flux();
常用Api
mono
.doOnNext(num -> process(num))//不需要返回值
.doOnError(throwable -> System.out.println(throwable.getMessage()))//相当于catch异常
.flatMap(num -> Mono.just(1))//需要返回值
.onErrorReturn(1)//放出错时返回什么值
.then(//当上一个Mono执行完之后执行这里的Mono
Mono.just("100")
.doOnNext(str -> process(str))
)
//.block()//阻塞执行当前mono,并且等待其执行完毕
.subscribe();//异步执行当前Mono,和Thread的start方法有相似的功能
常见问题
我的Mono/Flux为什么不执行?
- 没有调用subscribe或block方法
- 没有被消费
.flatMap(new Function<List<Integer>, Mono<?>>() {
@Override
public Mono<?> apply(List<Integer> integers) {
//这里Mono虽然没有显示的调用subscribe或block,但是被Funcation方法消费了,所以会执行
return mono;
}
})