文章目录
- java异步01——初识reactor
- reactor介绍
- Flux
- Mono
- 简单看一下Flux和Mono的api
- 订阅
- generate
- create
- handle
- Schedulers
- 线程模型
- 异常处理
- 常规处理
- transform操作符
java异步01——初识reactor
reactor介绍
Reactor是一个面向JVM(这意味着支持kotlin或者其他语言)的非阻塞响应式编程,具有高效的demand管理(以管理“背压”的形式)。它直接与Java 8功能(lambda、stream)集成在一起,特别是CompletableFuture,Stream和Duration。
Flux
Flux 是标准的Publisher,它表示0到N个发射项目的异步序列。会发出:OnNext,OnError,onComplete三种信号。
Mono
只发送一项的Pubilisher,有一些运算符可以返回Flux。
使用一个空的Mono <Void>表示无值异步过程。
简单看一下Flux和Mono的api
flux
Flux<String> seq1 = Flux.just("foo", "bar", "foobar");//直接赋值创建flux
List<String> iterable = Arrays.asList("foo", "bar", "foobar");
Flux<String> seq2 = Flux.fromIterable(iterable);//利用迭代器创建一个flux
Flux<Integer> numbersFromFiveToSeven = Flux.range(5, 3); //从5到7的flux,第二个参数表示产生的个数
mono
Mono<String> noData = Mono.empty(); //创建一个空mono
Mono<String> data = Mono.just("foo");//创建一个mono
订阅
只有订阅发生了,流才会开始
订阅接口有:
subscribe();
subscribe(Consumer<? super T> consumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer,
Runnable completeConsumer);
subscribe(Consumer<? super T> consumer,
Consumer<? super Throwable> errorConsumer,
Runnable completeConsumer,
Consumer<? super Subscription> subscriptionConsumer);
也可以通过继承抽象类BaseSubscriber
的实例来入参subscribe
public class ReactorTest {
public static void main(String[] args){
SampleSubscriber<Integer> ss = new SampleSubscriber<Integer>();
Flux<Integer> ints = Flux.range(1, 4);
ints.subscribe(i -> System.out.println(i),
error -> System.err.println("Error " + error),
() -> {System.out.println("Done");},
s -> s.request(10));
ints.subscribe(ss);
}
}
class SampleSubscriber<T> extends BaseSubscriber<T> {
public void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribed");
request(1);//请求一个资源
}
public void hookOnNext(T value) {
System.out.println(value);
request(1);//请求一个资源
}
}
输出:
1
2
3
4
Done
Subscribed
1
2
3
4
通过输入Subscriber
的方式来订阅事件的话,需要使用request
来向数据源请求事件
generate
Flux.generate(Callable<S>, BiFunction<S, SynchronousSink<T>, S>)
其中Callable<S>
是个回调函数,可以产生一个state,S就是State的类型
BiFunction<S, SynchronousSink<T>, S>
是迭代递归函数,输入有两个输入:S
和SynchronousSink<T>
,S
是state,SynchronousSink<T>
是sink,最后一个是S,是返回值类型,也是一个state。
SynchronousSink<T>
的API是:
public interface SynchronousSink<T> {
void complete();//给出完成信号
Context currentContext();//获取上下文
void error(Throwable e);//抛出异常
void next(T t);//定义flux中下一个元素
}
用来构造一个Flux,逐个产生元素
Flux<String> flux = Flux.generate(
() -> 0,
(state, sink) -> {
sink.next("3 x " + state + " = " + 3*state);
return state + 1;
});
首先() -> 0
产生一个state,然后这个state和sink作为每次迭代的入参,每次迭代的过程通过sink.next
来指定下一个值,通过sink.complete
标志迭代结束,然后返回一个更新的state,以便下次迭代根据state来生成新的值。值得说明的是,在一个generate中,sink.next
不能调用两次。
create
这个方法用起来和generate差不多(看原理上是有不小差距,但是我从api上没有体会到),并且sink.next
可以调用多次
例子:
public class ReactorTest {
public static void main(String[] args){
Flux<String> flux = Flux.create(sink->{
for(int i = 0; i < 10; i++){
sink.next("3 * " + i + " = " + (3*i));
}
});
CoreSubscriber<String> coreSubscriber = new SampleSubscriber();
flux.subscribe(coreSubscriber);
}
}
class SampleSubscriber<T> extends BaseSubscriber<T> {
public void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribed");
request(1);
}
public void hookOnNext(T value) {
System.out.println(value);
request(1);
}
}
handle
接在Flux已有的数据源上使用,可以看成是滤波
public class ReactorTest {
public static void main(String[] args){
Flux<String> flux = Flux.create(sink->{
for(int i = 0; i < 10; i++){
sink.next("3 * " + i + " = " + (3*i));
}
}).handle((i,sink)->{//进行过滤
sink.next(i+" hello");
});
CoreSubscriber<String> coreSubscriber = new SampleSubscriber();
flux.subscribe(coreSubscriber);
}
}
class SampleSubscriber<T> extends BaseSubscriber<T> {
public void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribed");
request(1);
}
public void hookOnNext(T value) {
System.out.println(value);
request(1);
}
}
Schedulers
在reactor中,可以通过选择schedulers来选择并发模型
- 当前线程(Schedulers.immediate())
- 可重用单线程(Schedulers.single())
- 专一单线程(Schedulers.newSingle())
- 弹性线程池(Schedulers.elastic())
- 固定大小线程池(Schedulers.parallel())创建和cpu个数相同的线程
线程模型
- publishOn强制下一个操作符运行在一个不同的线程上
- subscribeOn强制上一个操作符运行在一个不同的线程上
异常处理
在响应式流中,错误是终止事件,他会沿着操作链向下传递,直到遇到OnError方法
常规处理
输入异常处理函数,例如:
public class ReactorTest {
public static void main(String[] args){
Flux<String> flux = Flux.create(sink->{
for(int i = 0; i < 10; i++){
sink.next("3 * " + i + " = " + (3*i));
}
sink.error(new IllegalAccessError());
}).handle((i,sink)->{
sink.next(i+" hello");
});
flux.subscribe(System.out::println, (t)->System.err.println("catch a error"));
}
}
transform操作符
拼接处理操作符