异步非阻塞实现方式
回调
-
实现方式
-
回调方式会造成回调地狱
- 回调很难将逻辑组合起来,代码难以理解和维护。
A(callback(){
success(){
//一层
B(callback(){
success(){
//二层
C(callback(){
success(){
//三层
...
}
err(e){
}
})
}
err(e){
}
})
}
err(e){
}
});
future callable completablefuture
- future
- 1.invokeall()异步并发调用,获取返回结果依然是阻塞的get(),确实可以获取异步任务的执行结果,但是获取其结果还是会阻塞调用线程的,并没有实现完全异步化处理,要么使用isDone()轮询地判断Future是否完成,这样会耗费CPU的资源。
- 2.大量的应用会写出如下代码,可读性差且不优雅
public Future<Future<T>>> xxx();
- CompletableFuture
- CompletableFuture提供了非常强大的Future的扩展功能(50多个api),可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法,完成整个异步流程的编排。
- 在异步的任务完成后,需要用其结果继续操作时,无需等待。可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理,让主线程彻底解放出来,它避免了传统回调最大的问题,弥补了Future模式的缺点,实现了实际意义上的异步处理。
Reactive 响应式编程
- 指的是一种面向数据流并传播事件的异步编程范式
- 响应式宣言(要求,思想)
- 1.即时响应:系统在各种情况下都会尽全力保证及时响应。
- 2.回弹性:系统在面临故障时依然保持快速响应。
- 3.可伸缩性:系统在不同的负载下都能保持快速的响应。
- 4.消息驱动:响应式系统依赖异步的消息传递, 以确定各种组件的边界, 并确保松耦合、隔离性。
Reactor
- Reactor 是一个支持响应式流(Reactive Streams)的轻量级JVM基础库,是对设计模式观察者模式的扩展,用来支持对数据和事件的响应,帮助应用高效,异步地传递消息。它有非常丰富的操作符(过滤、合并、转换等)来对数据进行处理,封装一个非常好用的响应式/流式调用框架。与他相似的类库有 RxJava, RxJs, JDK9 Flow 等。
- 核心是异步非阻塞、函数式编程、事件驱动的思想。
- 实现原理
- 观察者模式
- Subject: 可观察者或者是被观察者(生产者),也叫做数据源或者发射源,数据源发射的数据通常也叫做事件。
- Observer:观察者(也叫消费者、订阅者),监听Subject发射的数据并做出响应
- Push 模式
- java8中的Stream是pull模式,下游从上游拉数据的过程,它会有中间操作例如 map filter 和 reduce,和终止操作例如 collect 等,只有在终止操作时才会真正的拉取数据。
- java中常用的数据遍历Iterator类也是一个pull拉模式来消费数据,判断是否有数据(hasNext()方法),获取数据(next())。Reactor中,数据源主动的告诉消费者发射什么事件(onNext()),事件发射什么时候结束(onComplete()),以及可能出现的报错(onError())。
Pull (Iterable) | Push (Observable) |
---|---|
T next() | onNext(T) |
throws Exception | onError(Throwable) |
return | onCompleted() |
-
反压(Backpressure)
- 反压出现的场景:上下游运行在不同的线程中,且上游发射数据速度大于下游接收处理数据的速度,也就是下游的处理能力不够了或者是Buffer出现溢出。因此Reactor中提供了Flowable这种可以设置丢弃策略的可观察者对象。
-
flux简单使用,先感受一下flux
- 被观察者对象.操作1().操作2().subscribe(观察者对象)
- Flux调用subscribe方法时,相当于subject发出了一个Event,从而让订阅此事件的观察者进行消费。
Flux.just("Tom", "Bob", "zhangsan", "lisi")
.map(s -> s.concat("@163.com"))
.filter(s -> s.length() > 10)
.subscribe(System.out::println);
- 调用链分析
Mono.just(1).map(v->{
return 200;
}).filter(v-> {
return v>=200;
}).