状态模式 java-Java观察者模式上及萨博涵五六:线程重启带参
发布时间:2023-07-09 09:07 浏览次数:次 作者:佚名
由上回书中所提及的只是一个简单的demo,没有充分考虑到实际的开发场景。在往实际项目中套的时候,发现还是有必要再深入一下。
Java观察者模式上
及萨博涵五六,公众号:码农智涵的程序人生【经验与坑】Java监控多线程,意外退出线程后自动重启Demo
在实际业务当中,启动线程的时候常常需要携带一些参数来初始化线程内部的工作。昨天并没有提到这一问题,而且仅仅使用了一个线程做测试并不严谨。这次将设置两个线程并加入线程重启带参的功能。

(1)添加一个参数实体类 ListenEntity.java
package entity;public class ListenEntity {private String string;private String string2;public String getString() {return string;}public void setString(String string) {this.string = string;}public String getString2() {return string2;}public void setString2(String string2) {this.string2 = string2;}}

每一次线程出现崩溃时就会在Catch中触发 doBusiness 方法,通过 doBusiness方法触发 Listener (观察者)中的 update 方法进行重启线程。
(2)被观察者 RunTread.java

//被观察者public class RunThread extends Observable implements Runnable{ListenEntity listenEntity = new ListenEntity();public void setListenEntity(ListenEntity listenEntity) {this.listenEntity = listenEntity;}//此方法一被调用,立马通知观察者,在本demo中是监听线程public void doBusiness(){if(true){super.setChanged();}notifyObservers(this.listenEntity);}@Overridepublic void run() {// TODO Auto-generated method stubint c = 0;//模拟线程运行一段事件之后退出while(true){System.out.println("Running-"+c+" "+new Date());System.out.println(Thread.currentThread().getName()+"正在执行");try{System.out.println("线程睡眠2秒");Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();doBusiness();break;}c++;//模拟抛出异常try{if(c==2){String str = null;str.length();//这里由于声明str为空,所以会报错(模拟线程异常崩溃)}}catch(Exception e){e.printStackTrace();doBusiness();//在抛出异常时调用,通过观察者,让其重启线程break;}}}public static void main(String[] args) {//声明第一个线程对象 并为其声明观察者对象 listener1ListenEntity listenEntity = new ListenEntity();listenEntity.setString("线程1携带参数1");listenEntity.setString2("线程1携带参数2");RunThread runThread1 = new RunThread();runThread1.setListenEntity(listenEntity);Listener listener1 = new Listener();runThread1.addObserver(listener1);//声明第二个线程对象 并声明第二个观察者对象 listener2ListenEntity listenEntity2 = new ListenEntity();listenEntity2.setString("线程2携带参数1");listenEntity2.setString2("线程2携带参数2");RunThread runThread2 = new RunThread();runThread2.setListenEntity(listenEntity2);Listener listener2 = new Listener();runThread2.addObserver(listener2);//启动多线程Thread thread1 = new Thread(runThread1,"线程1");Thread thread2 = new Thread(runThread2,"线程2");thread1.start();thread2.start();}}
notifyObservers(this.listenEntity);

可以看到状态模式 java,主要的变化的位置就在这个 notifyObservers方法的参数上,上次使用的只是它的初级版本没啥实际用处。但实际上它在设计时就给出了后续业务层面应用的余地。我们将出现猝死的线程复活所需要的参数通过 notify 大哥传给观察者的update方法,让观察者大夫赶快救救孩子。
看一下源码:
public void notifyObservers(Object arg) {/** a temporary array buffer, used as a snapshot of the state of* current Observers.*/Object[] arrLocal;synchronized (this) {/* We don't want the Observer doing callbacks into* arbitrary code while holding its own Monitor.* The code where we extract each Observable from* the Vector and store the state of the Observer* needs synchronization, but notifying observers* does not (should not). The worst result of any* potential race-condition here is that:* 1) a newly-added Observer will miss a* notification in progress* 2) a recently unregistered Observer will be* wrongly notified when it doesn't care*/if (!changed)return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}
这里notifyObservers(Object obj)的参数对应的就是 update 方法的第二个参数。根据源码可以看出状态模式 java,一旦被观察者的状态改变了,观察者会在处理这个问题的时候上锁,对当前状态进行释放,然后进入for循环中对众多观察者的update方法一一调用。
(3)观察者 Listener.java
//观察者public class Listener implements Observer{@Overridepublic void update(Observable arg0, Object object) {// TODO Auto-generated method stubListenEntity listenEntity = (ListenEntity)object;System.out.println("线程死机");System.out.println("线程重启流程接收到的参数:"+listenEntity.getString());RunThread runThread = new RunThread();runThread.setListenEntity(listenEntity);runThread.addObserver(this);Thread thread = new Thread(runThread);thread.start();System.out.println("线程重启成功");}}
最后看一下结合实际后的效果:

上一篇
