并发编程:自定义并发类:12、自定义异步流(发布与订阅)

目录

主要内容(参考编程流)

一、主程序

二、发布者(Publisher)

三、发布任务类(PublisherTask)

四、订阅实体(ConsumerData)

五、订阅者(消费者Consumer extends Subscriber)

六、订阅信息(Subscription)

七、元素信息(News)

八、执行结果


主要内容(参考编程流

  • Flow.Publisher:发布者(提供一个方法来接收Subscriber,进行消息发布)
  • Flow.Subscriber:订阅者(提供4个方法,分别用于:订阅完毕时,出现异常时,新元素被请求时,发布者注册订阅者时。)
  • Flow.Subscription:订阅(提供发布者与消费者之间的订阅处理)

一、主程序

  1. 实现一个发布者(Publisher),两个消费者(Consumer extends Subscriber),让它们建立订阅关系。
  2. 创建元素(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]

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值