并发编程:自定义并发类:自定义异步流(发布与订阅)
目录
五、订阅者(消费者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]
本文介绍了一个自定义的异步流实现,通过发布订阅模式管理消息的发布与接收过程。使用了发布者(Publisher)、订阅者(Consumer)、订阅(Subscription)等组件,并通过线程池来处理发布的消息。
&spm=1001.2101.3001.5002&articleId=109129892&d=1&t=3&u=4c678f948d824927b29a2ef74020ece0)
620

被折叠的 条评论
为什么被折叠?



