目录
五、订阅者(消费者Consumer extends Subscriber)
主要内容(参考编程流)
- Flow.Publisher:发布者(提供一个方法来接收Subscriber,进行消息发布)
- Flow.Subscriber:订阅者(提供4个方法,分别用于:订阅完毕时,出现异常时,新元素被请求时,发布者注册订阅者时。)
- Flow.Subscription:订阅(提供发布者与消费者之间的订阅处理)
一、主程序
- 实现一个发布者(Publisher),两个消费者(Consumer extends Subscriber),让它们建立订阅关系。
- 创建元素(News),由发布者进行发布操作(发布操作会创建独立的发布任务,由执行器执行。)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 8.13、自定义异步流(发布与订阅)
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午3:19:33
*
*/
public class M {
public static void main(String[] args) {
var publisher = new MyPublisher();
var consumer1 = new Consumer("Consumer 1");
var consumer2 = new Consumer("Consumer 2");
publisher.subscribe(consumer1);
publisher.subscribe(consumer2);
System.out.println("M:start");
var news = new News();
news.setTitle("My first news");
news.setContent("This is the content");
news.setDate(new Date());
publisher.publish(news);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
news = new News();
news.setTitle("My second news");
news.setContent("This is the content for second news");
news.setDate(new Date());
publisher.publish(news);
System.out.println("M:end");
}
}
二、发布者(Publisher)
发布者包含订阅者(Subscriber)和订阅信息(Subscription)结合的实体(ConsumerData订阅实体)对象列表。
发布者包含执行器(ThreadPoolExecutor),发布者发布信息时,会将元素信息(News)和订阅实体构造成发布任务(PublisherTask),由执行器执行。
package xyz.jangle.thread.test.n8_xiii.asyncstream;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.Flow.Publisher;
import java.util.concurrent.Flow.Subscriber;
/**
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午4:16:54
*
*/
public class MyPublisher implements Publisher<News> {
private ConcurrentLinkedDeque<ConsumerData> consumers;
private ThreadPoolExecutor executor;
public MyPublisher() {
consumers = new ConcurrentLinkedDeque<ConsumerData>();
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
}
@Override
public void subscribe(Subscriber<? super News> subscriber) {
ConsumerData consumerData = new ConsumerData();
consumerData.setConsumer((Consumer) subscriber);
var subscription = new MySubscription();
consumerData.setSubscription(subscription);
subscriber.onSubscribe(subscription);
consumers.add(consumerData);
}
/**
* 发布元素(为每个订阅者创建一个线程并提交给执行器执行。
* @param news
*/
public void publish(News news) {
consumers.forEach(consumerData -> {
try {
executor.execute(new PublisherTask(consumerData, news));
} catch (Exception e) {
consumerData.getConsumer().onError(e);
}
});
}
}
三、发布任务类(PublisherTask)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
/**
* 发布任务类
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午4:07:54
*
*/
public class PublisherTask implements Runnable {
private ConsumerData consumerData;
private News news;
public PublisherTask(ConsumerData consumerData, News news) {
super();
this.consumerData = consumerData;
this.news = news;
}
@Override
public void run() {
MySubscription subscription = consumerData.getSubscription();
if (!subscription.isCanceled() && subscription.getRequested() > 0) {
consumerData.getConsumer().onNext(news);
subscription.decreaseRequested();
}
}
}
四、订阅实体(ConsumerData)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
/**
* 订阅者信息实体
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午4:03:35
*
*/
public class ConsumerData {
private Consumer consumer;
private MySubscription subscription;
public Consumer getConsumer() {
return consumer;
}
public void setConsumer(Consumer consumer) {
this.consumer = consumer;
}
public MySubscription getSubscription() {
return subscription;
}
public void setSubscription(MySubscription subscription) {
this.subscription = subscription;
}
}
五、订阅者(消费者Consumer extends Subscriber)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.Flow.Subscription;
/**
* 订阅者(消费者)
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午3:25:14
*
*/
public class Consumer implements Subscriber<News> {
private Subscription subscription;
private String name;
public Consumer(String name) {
super();
this.name = name;
}
@Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
System.out.println(Thread.currentThread().getName() + ":onSubscribe() ******");
}
@Override
public void onNext(News item) {
System.out.println(Thread.currentThread().getName() + ":" + name + ":onNext() ******" + item);
subscription.request(1);
}
@Override
public void onError(Throwable throwable) {
System.out.println(Thread.currentThread().getName() + ":onError() ******");
}
@Override
public void onComplete() {
System.out.println(Thread.currentThread().getName() + ":onComplete() ******");
}
}
六、订阅信息(Subscription)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
import java.util.concurrent.Flow.Subscription;
/**
* 订阅
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午3:37:50
*
*/
public class MySubscription implements Subscription {
private boolean canceled = false;
private long requested = 0;
@Override
public void request(long n) {
requested += n;
}
@Override
public void cancel() {
canceled = true;
}
public boolean isCanceled() {
return canceled;
}
public long getRequested() {
return requested;
}
public void decreaseRequested() {
requested--;
}
}
七、元素信息(News)
package xyz.jangle.thread.test.n8_xiii.asyncstream;
import java.util.Date;
/**
* 元素类
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月16日 下午3:23:03
*
*/
public class News {
private String title, content;
private Date date;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "News [title=" + title + ", content=" + content + ", date=" + date + "]";
}
}
八、执行结果
main:onSubscribe() ******
main:onSubscribe() ******
M:start
pool-1-thread-1:Consumer 1:onNext() ******News [title=My first news, content=This is the content, date=Fri Oct 16 16:52:44 CST 2020]
pool-1-thread-2:Consumer 2:onNext() ******News [title=My first news, content=This is the content, date=Fri Oct 16 16:52:44 CST 2020]
M:end
pool-1-thread-3:Consumer 1:onNext() ******News [title=My second news, content=This is the content for second news, date=Fri Oct 16 16:52:45 CST 2020]
pool-1-thread-4:Consumer 2:onNext() ******News [title=My second news, content=This is the content for second news, date=Fri Oct 16 16:52:45 CST 2020]