併發程式設計:自定義併發類:自定義非同步流(釋出與訂閱)
目錄
五、訂閱者(消費者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]
相關文章
- 釋出-訂閱方式實現非同步併發非同步
- python中socket+threading的自定義併發Pythonthread
- 併發程式設計(一)——同步類容器程式設計
- 多執行緒高併發程式設計(2) -- 可重入鎖介紹和自定義執行緒程式設計
- 併發程式設計(二)——併發類容器ConcurrentMap程式設計
- 使用ArcEngine開發自定義Tool併發布為GP服務
- 【進階之路】併發程式設計(三)-非阻塞同步機制程式設計
- 《java併發程式設計的藝術》併發工具類Java程式設計
- Java併發程式設計:Java的四種執行緒池的使用,以及自定義執行緒工廠Java程式設計執行緒
- 多執行緒合集(一)---訊號量,鎖,以及併發程式設計,自定義任務排程和awaiter執行緒程式設計AI
- java併發程式設計——執行緒同步Java程式設計執行緒
- 程式與執行緒、同步與非同步、阻塞與非阻塞、併發與並行執行緒非同步並行
- Go 併發程式設計 - 併發安全(二)Go程式設計
- IDEA自定義類註釋和方法註釋(自定義groovyScript方法實現多行引數註釋)Idea
- 併發程式設計程式設計
- Java併發程式設計---java規範與模式下的併發程式設計1.1Java程式設計模式
- C++編寫自定義TCP包併傳送C++TCP
- 自定義異常類
- 《JAVA併發程式設計實戰》原子變數和非阻塞同步機制Java程式設計變數
- JUC併發系列(八):併發程式設計常用輔助類CountDownLatch與CyclicBarrier(手敲程式碼示例)程式設計CountDownLatch
- IDEA自定義註釋Idea
- 併發程式設計-11.取消非同步工作程式設計非同步
- java併發程式設計:Thread類的使用Java程式設計thread
- Java併發程式設計-鎖及併發容器Java程式設計
- 併發程式設計之:JUC併發控制工具程式設計
- java併發程式設計系列:java併發程式設計背景知識Java程式設計
- java 併發程式設計Java程式設計
- 併發程式設計—— LinkedTransferQueue程式設計
- 併發程式設計(ReentrantLock)程式設計ReentrantLock
- Go 併發程式設計Go程式設計
- golang併發程式設計Golang程式設計
- Golang 併發程式設計Golang程式設計
- Python併發程式設計Python程式設計
- 併發程式設計 synchronized程式設計synchronized
- 併發程式設計(四)程式設計
- 併發程式設計(二)程式設計
- Java併發程式設計Java程式設計
- 併發程式設計13程式設計