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示例 ...
随机推荐
- 【JavaSE】泛型
Java泛型 2019-07-05 22:00:24 by冲冲 1. 泛型的引例 1 List list = new ArrayList(); 2 list.add(1022); //向集合中添加 ...
- BehaviorTree.CPP行为树BT的介绍(一)
节点类型 ControlNode是可以具有1到N个子节点的节点.一旦接收到tick,tick可以传播到一个或多个子节点. DecoratorNodes与ControlNode相似,但只能有一个子节点. ...
- 安卓手机添加系统证书方法(HTTPS抓包)
目录 1. 导出证书(以Charles为例) 2. 安卓证书储存格式 3. 将导出的证书计算hash值 4. 生成系统系统预设格式证书文件 5. 上传证书 安卓7.0以后,安卓不信任用户安装的证书,所 ...
- git添加新账号
1,在linux上添加账号 useradd test passwd test usermod -G gitgroup test 将test账号的组改为和git一样的组gitgroup git所在 ...
- printf 的 转义词 -转
\n 换行 \r 回车键 \b 退后一格 \f 换页 \t 水平制表符 \v 垂直制表符 \a 发出鸣响 \? 插入问号 \" 插入双引号 \' ...
- Git五个常见问题及解决方法
一.删除远程仓库上被忽略的文件 由于种种原因,一些本应该被忽略的文件被我们误操作提交到了远程仓库了.那么我们该怎么删除这些文件呢? 以误提交了.idea目录为例,我们可以通过下面的步骤处理: 1)我们 ...
- 【模板】网络最大流(EK、Dinic、ISAP)(网络流)/洛谷P3376
题目链接 https://www.luogu.com.cn/problem/P3376 题目大意 输入格式 第一行包含四个正整数 \(n,m,s,t\),分别表示点的个数.有向边的个数.源点序号.汇点 ...
- 截取字符串、拼接字符串【c#】
string compname="1与3"; String[] name = compname.Split('与'); string namer=name[0]; namer=1 ...
- C#表格GridView显示2位百分比
<asp:BoundField HeaderText="占比" DataField="number" DataFormatString="{0: ...
- Hadoop入门 常见错误及解决方案
常见错误及解决方案 目录 常见错误及解决方案 ResourceManager连接失败 root用户和ranan用户两个用户启动集群不统一 不识别主机名 DataNode和NameNode进程同时只能工 ...