一、普通观察者模式
观察者模式:一般分为Subject(主题即目标对象,一旦发生改变要发出通知),observer(观察者一旦目标发生改变,自动触发回调方法)
/**
* 观察者模式:目标对象
*
*/
@Getter
public class Subject {
//定义观测者集合,存需要通知对象
private List<Observer> observers = new ArrayList<>();
private int state;
/**
* 更新目标对象的状态
*
* @param state 目标对象的状态
*/
public void setState(int state) {
if (state == this.state) {
return;
}
this.state = state;
//一旦发生改变通知所有观察者
notifyAllObservers();
}
/**
* 添加观察者对象
*
* @param observer 观察者对象
*/
public void attach(Observer observer) {
observers.add(observer);
}
/**
* 通知所有的观察者对象
*/
private void notifyAllObservers() {
observers.forEach(Observer::update);
}
}
//===========================================================
/**
* 观察者抽象类
*
*/
public abstract class Observer {
protected Subject subject;
public Observer(Subject subject) {
this.subject = subject;
this.subject.attach(this); //构建的同时将自身加入观测集合
}
protected abstract void update();
}
//==========================================================
/**
* 观察者的具体实现-二进制观察者
*
*/
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
super(subject);
}
@Override
public void update() {
System.out.println("Binary String:" + Integer.toBinaryString(subject.getState()));
}
}
//============================================================
/**
* 观察者的具体实现-八进制观察者
*
*/
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
super(subject);
}
@Override
public void update() {
System.out.println("Octal String:" + Integer.toOctalString(subject.getState()));
}
}
//==========================================
/**
* Observer观察者模式测试类
*
*/
public class ObserverClient {
public static void main(String[] args) {
Subject subject = new Subject();
new BinaryObserver(subject);
new OctalObserver(subject);
System.out.println("=========");
subject.setState(1);
System.out.println("=========");
subject.setState(1);
System.out.println("=========");
subject.setState(17);
}
//OUTPUT
/* =========
Binary String:1
Octal String:1
=========
=========
Binary String:10001
Octal String:21*/
}
二、多线程
利用观察者模式观察线程运行情况,例子中仅仅是做出了打印,实际根据具体业务做相应的操作
/**
* 目标对象线程
*
*/
public abstract class ObservableRunnable implements Runnable {
/**
* 一个线程对应一个观察者
*/
protected final LifeCycleListener listener;
public ObservableRunnable(LifeCycleListener listener) {
this.listener = listener;
}
/**
* 线程状态改变时,通知观察者对象
*
* @param event 线程状态事件
*/
protected void notifyChange(RunnableEvent event) {
listener.onEvent(event);
}
}
//===============================================
/**
* 线程状态
*/
public enum RunnableState {
RUNNING, ERROR, DONE;
}
/**
* 线程事件
*/
@Getter
public class RunnableEvent {
private final RunnableState state;
private final Thread thread;
private final Throwable cause;
public RunnableEvent(RunnableState state, Thread thread, Throwable cause) {
this.state = state;
this.thread = thread;
this.cause = cause;
}
}
//=============================================
/**
* 线程生命周期观察者接口
*/
public interface LifeCycleListener {
/**
* 线程状态改变时触发方法
*
* @param event 触发事件
*/
void onEvent(RunnableEvent event);
}
/**
* 线程生命周期观察者实现类
*/
public class ThreadLifeCycleObserver implements LifeCycleListener {
private static final Object LOCK = new Object();
@Override
public void onEvent(RunnableEvent event) {
synchronized (LOCK) {
System.out.println("The runnable [" + event.getThread().getName() + "] data changed and state is [" + event.getThread().getState() + "].");
if (event.getCause() != null) {
System.out.println("THe runnable [" + event.getThread().getName() + "] process failed.");
event.getCause().printStackTrace();
}
}
}
}
//=============================================
/**
* 线程生命周期观察者测试类
*/
public class ThreadLifeCycleClient {
public static void main(String[] args) {
ThreadLifeCycleObserver observer = new ThreadLifeCycleObserver();
Stream.of("1", "2").forEach(id -> new Thread(new ObservableRunnable(observer) {
@Override
public void run() {
try {
notifyChange(new RunnableEvent(RunnableState.RUNNING, Thread.currentThread(), null));
System.out.println("query for the id " + id);
Thread.sleep(1000L);
// int x = 1 / 0;
notifyChange(new RunnableEvent(RunnableState.DONE, Thread.currentThread(), null));
} catch (Exception e) {
notifyChange(new RunnableEvent(RunnableState.ERROR, Thread.currentThread(), e));
}
}
}, id).start());
}
}
//OUTPUT
/* The runnable [2] data changed and state is [RUNNABLE].
The runnable [1] data changed and state is [RUNNABLE].
query for the id 2
query for the id 1
The runnable [1] data changed and state is [RUNNABLE].
THe runnable [1] process failed.
The runnable [2] data changed and state is [RUNNABLE].
THe runnable [2] process failed.
java.lang.ArithmeticException: / by zero
at com.tuyrk.chapter04.lifecycle.ThreadLifeCycleClient$1.run(ThreadLifeCycleClient.java:21)
at java.lang.Thread.run(Thread.java:748)
java.lang.ArithmeticException: / by zero
at com.tuyrk.chapter04.lifecycle.ThreadLifeCycleClient$1.run(ThreadLifeCycleClient.java:21)
at java.lang.Thread.run(Thread.java:748)*/