背压:
是指由于生产者生产速度过快,而造成消费者无法及时处理更多的事件而产生的问题,背压是该问题的一个解决方案,它可以通过主动从生产者拉取事件消费而避免过多事件推送而无法处理的情况,或者减缓事件发布的速率直到可以处理更多的事件,实现事件流的流量控制。
reactive stream是一套基于发布/订阅模式的数据处理的规范,主要目标是管理跨异步边界的流数据交换 - 考虑将元素传递到另一个线程或线程池 - 同时确保接收方不会强制缓冲任意数量的数据。换句话说,背压是该模型的组成部分,以便允许在线程之间调解的队列有界。如果背压信号是同步的,则异步处理的好处将被否定,因此需要注意强制实施Reactive Streams实现的所有方面的完全非阻塞和异步行为。对应的是flow api
publisher:数据的发布者、生产者
public void subscribe(Subscriber<? super T> subscriber);//与订阅者建立关系
subscriber:数据的订阅者、消费者
public void onSubscribe(Subscription subscription);//建立订阅关系时执行
public void onNext(T item);//数据接收时执行
public void onError(Throwable throwable);//出错时执行
public void onComplete();//发布者无更多数据时调用,表示处理完毕时执行
subscription:维持发布者与订阅者的关系,一个订阅认证
public void request(long n);//请求n条数据
public void cancel();//取消请求数据
processor:过滤器,数据处理器,继承了publisher和subscriber
下面这个例子是
package com.gdut.nettydemo.flow;
import java.util.concurrent.*;
import java.util.stream.IntStream;
/**
* @author lulu
* @Date 2019/8/7 13:09
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
ExecutorService fix= Executors.newFixedThreadPool(3);
SubmissionPublisher<Integer> publisher = new SubmissionPublisher();
//订阅者
Flow.Subscriber subscriber = new Flow.Subscriber() {
private Flow.Subscription subscription;
long start=0;
@Override
public void onSubscribe(Flow.Subscription subscription) {
start=System.currentTimeMillis();
System.out.println("haha");
this.subscription = subscription;
this.subscription.request(1);
}
@Override
public void onNext(Object item) {
try {
//睡眠时间如果更长的话,会发现sumbit方法被阻塞了,而offer方法则不会阻塞,会执行删除该事件的方法,如果符合条件会进行重投
TimeUnit.MILLISECONDS.sleep(1000);
/* fix.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"接收到数据" + item);
}
});*/
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"接收到数据" + item);
this.subscription.request(3);
}
@Override
public void onError(Throwable throwable) {
this.subscription.cancel();
}
@Override
public void onComplete() {
System.out.println("处理完毕"+(System.currentTimeMillis()-start));
// fix.shutdown();
}
};
//建立关系
publisher.subscribe(subscriber);
//submit
// IntStream.range(0,1000).forEach(publisher::submit);
IntStream.range(0,300).forEach(e->{
int t= publisher.offer(e,70,TimeUnit.MILLISECONDS,(pr,d)->
d>280
);
System.out.println(t+"--"+e);
});
publisher.close();
Thread.currentThread().join(3000000);
}
}
符合offer里的条件会执行断点的retrayOffer方法,即使可以重投,在规定时间内没有空位就默认为失败。
也可以自定义Processor来对数据做一定的数据处理
package com.gdut.nettydemo.flow;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;
public class ProcessorDemo extends SubmissionPublisher<String>
implements Flow.Processor<Integer, String> {
private Flow.Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
// 保存订阅关系, 需要用它来给发布者响应
this.subscription = subscription;
// 请求一个数据
this.subscription.request(1);
}
@Override
public void onNext(Integer item) {
// 保留能整除2的
if (item %2==0) {
this.submit("转换后的数据:" + item);
}
this.subscription.request(1);
// 达到了目标, 调用cancel告诉发布者不再接受数据了
// this.subscription.cancel();
}
@Override
public void onError(Throwable throwable) {
// 出现了异常(例如处理数据的时候产生了异常)
throwable.printStackTrace();
this.subscription.cancel();
}
@Override
public void onComplete() {
// 关闭
this.close();
}
}
package com.gdut.nettydemo.flow;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;
import java.util.stream.IntStream;
/**
* @author lulu
* @Date 2019/8/7 21:12
*/
public class Test2 {
public static void main(String[] args) throws InterruptedException {
SubmissionPublisher publisher=new SubmissionPublisher();
ProcessorDemo processor=new ProcessorDemo();
Flow.Subscriber subscriber=new Flow.Subscriber() {
private Flow.Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription=subscription;
this.subscription.request(1);
}
@Override
public void onNext(Object item) {
System.out.println("接收到数据"+item);
this.subscription.request(1);
}
@Override
public void onError(Throwable throwable) {
this.subscription.cancel();
}
@Override
public void onComplete() {
System.out.println("处理完了");
}
};
//建立关系
publisher.subscribe(processor);
processor.subscribe(subscriber);
IntStream.range(0,100).forEach(publisher::submit);
publisher.close();
Thread.currentThread().join(10000);
}
}
参考博文: