java 多线程 发布订阅模式:发布者java.util.concurrent.SubmissionPublisher;订阅者java.util.concurrent.Flow.Subscriber
1,什么是发布订阅模式?
2,发布订阅模式的4个角色
- Flow.Publisher: 代表数据发布者,生产者
- Flow.Subscriber: 表数据订阅者、消费者
- Flow.Subscription: 表发布者和订阅者之间的链接纽带。订阅者既可通过调用该对象的request()方法来获取数据项,也可通过调用对象的cancel()方法来取消订阅。
- Flow.Processor: 数据处理器,它可同时作为发布者和订阅者使用
测试用例:发布者每秒钟发布一条消息,订阅者每秒钟订阅一条消息。
注意:订阅者处理消息,依赖当前线程的存活状态,如果发布消息后当前程序代码运行完毕会立即退出,订阅者来不及执行任何程序。
此例 用锁保持当前线程存活
import java.util.List;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**
* @ClassName PublisherFlowSubscriber
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/28.
*/
public class PublisherFlowSubscriber {
/**
* 定义用来保持线程不退出的锁
*/
private static Lock lock = new ReentrantLock(true);
private static Condition condition = lock.newCondition(); public static void main(String[] args) throws InterruptedException {
/**
* 定义一个发布者,需要设定要发送消息的泛型数据类型
*/
SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
/**
* 定义一个订阅者
*/
MySubscirber<String> subscirber = new MySubscirber<>("订阅者1");
MySubscirber<String> subscirber2 = new MySubscirber<>("订阅者2");
/**
* 通过发布者配置订阅者 会触发订阅者的onSubscribe方法,他们之间的链接纽带会通过参数传递给onSubscribe方法,如果注册失败会触发onError方法
*/
publisher.subscribe(subscirber);publisher.subscribe(subscirber2); /**
* 测试发布消息
*/
List<String> list = List.of("张三", "李四", "王五", "赵六");
list.forEach(string -> publisher.submit(string)); //向订阅者发布数据,需要保持前台的线程存活,否则当前线程执行结束,发布者和订阅者都被销毁了。
/**
* 关闭消息发布
*/
publisher.close(); //关闭后,如果当前线程未退出,待订阅者所有消息都处理完毕才会运行订阅者的onComplete方法
lock.lock();
//抛出锁
condition.await();
lock.unlock(); } /**
* 定义订阅者类,需要注意实现接口Flow.Subscriber 实现其泛型传递
*/
private static class MySubscirber<T> implements Flow.Subscriber<T>{
/**
* 订阅者自定义的属性,名字,关联的订阅平台
*/
private String name;
private Flow.Subscription subscription; public MySubscirber(String name) {
this.name = name;
} /**
* 订阅的时候触发的方法
* @param subscription 订阅者被关联的订阅平台
*/
@Override
public void onSubscribe(Flow.Subscription subscription) {
System.out.println(name + "开启订阅" + subscription);
/**
* 从订阅平台获取一条消息
*/
subscription.request(1);
/**
* 将平台实例保存,便于复用
*/
this.subscription = subscription;
} /**
* 获取一条数据后触发的方法
* @param
*/
@Override
public void onNext(T t) {
System.out.println(name + "获取到了一条数据:" +t);
//再次获取一条数据...自循环触发自己循环调用,一直将所有数据获取完毕
subscription.request(1);
/**
* 模拟处理耗时
*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* 订阅出错时运行的方法
* @param throwable 错误对象
*/
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
} /**
* 发布者停止发布,且订阅者处理完接收数据后,触发该方法
*/
@Override
public void onComplete() {
System.out.println(name + "发布者关闭了发布");
lock.lock();
condition.signalAll();
lock.unlock();
}
}
}

java 多线程 发布订阅模式:发布者java.util.concurrent.SubmissionPublisher;订阅者java.util.concurrent.Flow.Subscriber的更多相关文章
- Java 多线程编程之九:使用 Executors 和 ThreadPoolExecutor 实现的 Java 线程池的例子
线程池用来管理工作线程的数量,它持有一个等待被执行的线程的队列. java.util.concurrent.Executors 提供了 java.util.concurrent.Exe ...
- js里的发布订阅模式及vue里的事件订阅实现
发布订阅模式(观察者模式) 发布订阅模式的定义:它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布订阅模式在JS中最常见的就是DOM的事件绑定与触发 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- Java多线程面试题整理
部分一:多线程部分: 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速. ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列目录(共43篇)
最近,在研究Java多线程的内容目录,将其内容逐步整理并发布. (一) 基础篇 01. Java多线程系列--“基础篇”01之 基本概念 02. Java多线程系列--“基础篇”02之 常用的实现多线 ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...
随机推荐
- git添加新工程
git init git remote add origin 码云路径 git pull origin master 代码拉本地后 git add . git commit -m '新添加的文件内容描 ...
- jmeter链接数据库,信息全部填写正确,运行之后没有结果
之前遇到一个很苦恼的问题,jmeter链接数据库,数据库填写的资料全部都没有问题,在其他电脑jmeter上都可以正常链接,但是在我的电脑上运行却总是不出结果, 用mysql链接数据库也一切正常,一直找 ...
- 如何根据taxid(或taxname)快速获得taxname(或taxid)?
目录 需求 实现 需求 我有一个物种taxonomy ID的list,想获得相应的物种名,不要一个个去NCBI Taxonomy官网查.反之根据物种名list查询对应的taxid. 实现 因为之前没怎 ...
- PHP-FPM运行状态的实时查看及监控详解
https://www.jb51.net/article/97640.htm https://blog.csdn.net/Dr_cokiy/article/details/105580758
- PDFium 渲染
PDFium 是 Chromium 的 PDF 渲染引擎,许可协议为 BSD 3-Clause.不同于 Mozilla 基于 HTML5 的 PDF.js,PDFium 是基于 Foxit Softw ...
- [PE结构]导入表与IAT表
导入表的结构导入表的结构 typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for termi ...
- MYSQL获取更新行的主键ID 【转】
在某些情况下我们需要向数据表中更新一条记录的状态,然后再把它取出来,但这时如果你在更新前并没有一个确认惟一记录的主键就没有办法知道哪条记录被更新了. 举例说明下: 有一个发放新手卡的程序,设计数据库时 ...
- JTable 单元格合并 【转】
单元格合并 一.单元格合并.(1)我们可以使用Jtable的三个方法:getCellRect(),columnAtPoint(),and rowAtPoint().第一个方法返回一个单元格的边界(Re ...
- How exactly does Google AdWords work?
The key to how Google AdWords works is the Quality Score. Quality Score is generally how well an ad ...
- Spring整合Ibatis之SqlMapClientDaoSupport
前言 HibernateDaoSupport SqlMapClientDaoSupport . 其实就作用而言两者是一样的,都是为提供DAO支持,为访问数据库提供支持. 只不过HibernateD ...