概念不多做介绍,直接看代码,简易demo
public class FlowDemo {
public static void main(String[] args) {
//定义发布者
SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
//定义订阅者
Subscriber<Integer> subscriber = new Subscriber<Integer>() {
private Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
//保存订阅关系,用它来给发布者响应
this.subscription = subscription;
//告诉发布者需要一个数据
this.subscription.request(1);
}
@Override
public void onNext(Integer item) {
//接收到一个数据并做处理
System.out.println("接收到数据:" + item);
//处理完后再请求一个数据
this.subscription.request(1);
//或者已经达到目标,告诉发布者不再接收数据
// this.subscription.cancel();
}
@Override
public void onError(Throwable throwable) {
//出现异常
throwable.printStackTrace();
//告诉发布者不再接收数据
this.subscription.cancel();
}
@Override
public void onComplete() {
//全部处理完(发布者关闭)
System.out.println("处理完成");
}
};
//建立发布者和订阅者的订阅关系
publisher.subscribe(subscriber);
//产生数据并发布
publisher.submit(111);
publisher.submit(222);
publisher.submit(333);
//结束后关闭发布者
//正式环境放finally里或用try-resource确保关闭
publisher.close();
//延迟,否则主线程会很快
try {
Thread.currentThread().join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
实现了发布者和订阅者的关系,需要多注意的是,这里可做调节,如果处理的慢,处理下一个的频率就慢,反之就快,这里起到了调节发布者发送频率的作用。
再看一个:
这里的输入数据,过滤掉小于0的,并转成字符串发布出去。
class MyProcessor extends SubmissionPublisher<String>
implements Processor<Integer , String>{
private Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
this.subscription.request(1);
}
@Override
public void onNext(Integer item) {
System.out.println("处理器接收到数据:" + item);
if (item > 0){
this.submit(String.valueOf(item));
}
this.subscription.request(1);
// this.subscription.cancel();
}
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
this.subscription.cancel();
}
@Override
public void onComplete() {
System.out.println("处理器处理完成");
this.close();
}
}
public class FlowDemo2 {
public static void main(String[] args) {
SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
MyProcessor myProcessor = new MyProcessor();
publisher.subscribe(myProcessor);
Subscriber<String> subscriber = new Subscriber<>() {
private Subscription subscription;
@Override
public void onSubscribe(Subscription subscription) {
//保存订阅关系,用它来给发布者响应
this.subscription = subscription;
//告诉发布者需要一个数据
this.subscription.request(1);
}
@Override
public void onNext(String item) {
//接收到一个数据并做处理
System.out.println("订阅者接收到数据:" + item);
//处理完后再请求一个数据
this.subscription.request(1);
//或者已经达到目标,告诉发布者不再接收数据
// this.subscription.cancel();
}
@Override
public void onError(Throwable throwable) {
//出现异常
throwable.printStackTrace();
//告诉发布者不再接收数据
this.subscription.cancel();
}
@Override
public void onComplete() {
//全部处理完(发布者关闭)
System.out.println("处理完成");
}
};
myProcessor.subscribe(subscriber);
publisher.submit(-10);
publisher.submit(12);
publisher.close();
try {
Thread.currentThread().join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
这里发布者不直接跟订阅者建立关系,而是通过处理器。
那么发布者和订阅者是如何协调的呢?
通过断点可以看到,subscription里有个数组,,长度是32,最大可变为256,这里可视为缓冲池,把发布者发过来的消息缓存起来,消费的时候直接从这里取。
那么订阅者如何使发布者发布速度慢下来呢?发布者的submit方法是阻塞方法,当订阅者的缓冲池满了,submit就会被阻塞,就停下来了。
改下代码
public class FlowDemo {
public static void main(String[] args) {
//定义发布者
SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
//定义订阅者
Subscriber<Integer> subscriber = new Subscriber<Integer>() {
private Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
//保存订阅关系,用它来给发布者响应
this.subscription = subscription;
//告诉发布者需要一个数据
this.subscription.request(1);
}
@Override
public void onNext(Integer item) {
//接收到一个数据并做处理
System.out.println("接收到数据:" + item);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
//处理完后再请求一个数据
this.subscription.request(1);
//或者已经达到目标,告诉发布者不再接收数据
// this.subscription.cancel();
}
@Override
public void onError(Throwable throwable) {
//出现异常
throwable.printStackTrace();
//告诉发布者不再接收数据
this.subscription.cancel();
}
@Override
public void onComplete() {
//全部处理完(发布者关闭)
System.out.println("处理完成");
}
};
//建立发布者和订阅者的订阅关系
publisher.subscribe(subscriber);
//产生数据并发布
for (int i = 0 ; i < 1000 ; i ++){
System.out.println("生产数据:" + i);
publisher.submit(i);
}
//结束后关闭发布者
//正式环境放finally里或用try-resource确保关闭
publisher.close();
//延迟,否则主线程会很快
try {
Thread.currentThread().join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
一开始,会生成236条数据,因为缓冲池最大256,所以当到256后就不会再生成了
接下来每消费一条数据,就会再接着生产一条