java 广播模式_Java设计模式——观察者模式的灵活应用

灵感来源于一个猪队友给个人题目java

05848ce0925988f3eb9ca61ef8dd2066.png

看到这个,我抓住的关键字是:任何子任务失败,要通知全部子任务执行取消逻辑。dom

这不就是消息广播吗?观察者模式!ide

干活

首先是收听者测试

packagecom.example.broadcast;/*** 每一个节点便是广播者,也是收听者*/

public interfaceListener {/*** 设置调度中心*/

voidsetCenter(DispatchCenter center);/*** 主动通知其它收听者*/

voidnotice(String msg);/*** 本身收到通知的处理逻辑

*@parammsg*/

voidwhenReceived(String msg);/*** 收听者标志:惟一

*@return

*/String identify();

}

而后是调度中心this

packagecom.example.broadcast;/*** 调度中心*/

public interfaceDispatchCenter {/*** 广播

*@paramown 广播的时候,要排除本身

*@parammsg 广播消息*/

voidbroadcast(String own, String msg);/*** 添加收听者

*@paramlistener*/

voidaddListener(Listener listener);

}

调度中心实现spa

packagecom.example.broadcast;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;public class DispatchCenterImpl implementsDispatchCenter {private static final Map MAP = new ConcurrentHashMap<>();

@Overridepublic voidbroadcast(String own, String msg) {

MAP.forEach((k,v)->{//不用给本身发通知

if (!k.equals(own)){

v.whenReceived(msg);

}

});

}

@Overridepublic voidaddListener(Listener listener) {

listener.setCenter(this);

MAP.put(listener.identify(), listener);

}

}

剩下三个收听者线程

packagecom.example.broadcast;importjava.util.UUID;public class ListenerA implementsListener {privateDispatchCenter center;privateString identify;publicListenerA() {

identify=UUID.randomUUID().toString();

}

@Overridepublic voidsetCenter(DispatchCenter center) {this.center =center;

}

@Overridepublic voidnotice(String msg) {

center.broadcast(identify, msg);

}

@Overridepublic voidwhenReceived(String msg) {

System.out.println(this.getClass().getName() + "收到消息:" +msg);

}

@OverridepublicString identify() {returnidentify;

}

}

B和C除了类名不同,其余都同样,再也不赘述。目录以下3d

6c834281fe3c003d4de52bf13b6ac0e5.png

测试

packagecom.example.broadcast;importjava.util.Random;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;public classMain {public static voidmain(String[] args) {

DispatchCenter center= newDispatchCenterImpl();

ListenerA listenerA= newListenerA();

ListenerB listenerB= newListenerB();

ListenerC listenerC= newListenerC();

center.addListener(listenerA);

center.addListener(listenerB);

center.addListener(listenerC);

ExecutorService executorService= Executors.newFixedThreadPool(3);//A触发1条事件

executorService.submit(() ->{int i = 1;while (i > 0){

listenerA.notice(listenerA.getClass().getName()+ "说:我有" + new Random().nextInt(1000000) + "元");

i--;

}

});//B触发2条事件

executorService.submit(() ->{int i = 2;while (i > 0){

listenerB.notice(listenerB.getClass().getName()+ "说:我有" + new Random().nextInt(1000000) + "元");

i--;

}

});//C触发3条事件

executorService.submit(() ->{int i = 3;while (i > 0){

listenerC.notice(listenerC.getClass().getName()+ "说:我有" + new Random().nextInt(1000000) + "元");

i--;

}

});

executorService.shutdown();

}

}

输出:code

43d1fc0d1f155e1d01753a6d35bd94fe.png

流程图

a74b0464dd8d2da378f1e020ab2091b3.png

当其中的B节点,发生了错误,除了把本身处理好以外blog

1. 向调度中心发送广播请求,并携带须要的消息

2. 调度中心遍历收听者,挨个通知(执行)每个收听者接受消息的逻辑

关于中止任务

由于题目要求,【快速取消】全部子任务

关于线程中止的方法也有不少:

1. 优雅退出run方法

2. 暴力stop

3. run方法抛出异常

若是说要求,A异常了,B和C收到消息以后,线程当即中止,不能有一点迟疑,说实话我还没想到该怎么作。由于你要知道,实际上的任务的run方法内部,不太多是个while循环,人家可能就是个顺序执行,因此中止标志位的方式,并不适用。

而其它的方法,我也没想到很好的。我只能写个按照标志位中止的“玩具”

修改三个收听者代码和测试类

packagecom.example.broadcast;importlombok.SneakyThrows;importjava.util.Random;importjava.util.UUID;public class ListenerA implementsListener,Runnable {privateDispatchCenter center;privateString identify;publicListenerA() {

identify=UUID.randomUUID().toString();

}

@Overridepublic voidsetCenter(DispatchCenter center) {this.center =center;

}

@Overridepublic voidnotice(String msg) {

center.broadcast(identify, msg);

}

@Overridepublic voidwhenReceived(String msg) {

System.out.println(this.getClass().getName() + "收到消息:" +msg);

}

@OverridepublicString identify() {returnidentify;

}

@SneakyThrows

@Overridepublic voidrun() {//5秒以后,模拟发生异常

Thread.sleep(5000);

notice(this.getClass().getName() + "说:我有" + new Random().nextInt(1000000) + "元");

System.out.println(this.getClass().getName() + "程序异常,并已经传播了消息...");

}

}

packagecom.example.broadcast;importlombok.SneakyThrows;importjava.util.UUID;public class ListenerB implementsListener,Runnable {privateDispatchCenter center;privateString identify;private volatile Boolean stopFlag = false;publicListenerB() {

identify=UUID.randomUUID().toString();

}

@Overridepublic voidsetCenter(DispatchCenter center) {this.center =center;

}

@Overridepublic voidnotice(String msg) {

center.broadcast(identify, msg);

}

@Overridepublic voidwhenReceived(String msg) {

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "收到消息:" +msg);//中止当前线程

stopFlag = true;

}

@OverridepublicString identify() {returnidentify;

}

@SneakyThrows

@Overridepublic voidrun() {while (!stopFlag){

Thread.sleep(1000);

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "__B在执行任务");

}

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "__B Dead");

}

}

packagecom.example.broadcast;importlombok.SneakyThrows;importjava.util.UUID;public class ListenerC implementsListener,Runnable {privateDispatchCenter center;privateString identify;private volatile Boolean stopFlag = false;publicListenerC() {

identify=UUID.randomUUID().toString();

}

@Overridepublic voidsetCenter(DispatchCenter center) {this.center =center;

}

@Overridepublic voidnotice(String msg) {

center.broadcast(identify, msg);

}

@Overridepublic voidwhenReceived(String msg) {

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "收到消息:" +msg);//中止当前线程

stopFlag = true;

}

@OverridepublicString identify() {returnidentify;

}

@SneakyThrows

@Overridepublic voidrun() {while (!stopFlag){

Thread.sleep(1000);

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "__C在执行任务");

}

System.out.println(this.getClass().getName() + "_" + Thread.currentThread().getName() + "__C Dead");

}

}

测试

packagecom.example.broadcast;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;public classMain {public static voidmain(String[] args) {

DispatchCenter center= newDispatchCenterImpl();

ListenerA listenerA= newListenerA();

ListenerB listenerB= newListenerB();

ListenerC listenerC= newListenerC();

center.addListener(listenerA);

center.addListener(listenerB);

center.addListener(listenerC);

ExecutorService executorService= Executors.newFixedThreadPool(3);//A

executorService.submit(listenerA);//B

executorService.submit(listenerB);//C

executorService.submit(listenerC);

executorService.shutdown();

}

}

c6ad9b21d55de6a0ec4498cd8217720a.png

这个是这么多年第一个发到首页的,就是想问下你们怎样解决这种状况下的线程中止问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值