//监控线程是否死亡
package io.mycat.bigmem.util;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
/**
*@desc 监控线程是否死亡,然后执行回调方法.
*@author zhangwy @date 2017年2月21日 上午6:14:34
**/
public class ThreadDeathWatcher {
/*started 线程是否已经启动*/
private static AtomicBoolean started = new AtomicBoolean(false);
/*需要加入监控,或者不监控的待处理的队列*/
private static ConcurrentLinkedQueue<Entry> threadQueue = new ConcurrentLinkedQueue<Entry>();
/*正在处理的线程*/
private static Thread watchThread = null;
/*加入监控*/
public static void watche(Thread thread,Runnable task) {
if(thread == null) {
throw new NullPointerException("thread");
}
if(task == null) {
throw new NullPointerException("task");
}
if(!thread.isAlive()) {
throw new IllegalArgumentException("thread must be alive");
}
schedual(thread, task, true);
}
/*移除监控*/
public static void unWathe(Thread thread, Runnable task) {
if(thread == null) {
throw new NullPointerException("thread");
}
if(task == null) {
throw new NullPointerException("task");
}
schedual(thread, task, false);
}
/*线程任务的调度*/
private static void schedual(Thread thread, Runnable task, boolean isWatching) {
Entry entry = new Entry(thread, task, isWatching);
threadQueue.add(entry);
if(started.compareAndSet(false, true)) {
Watcher wathcer = new Watcher();
watchThread = new Thread(wathcer, "Deather watcher thread");
watchThread.setDaemon(true);
watchThread.start();
System.out.println(watchThread.getName() + " start ===========");
}
}
static final class Watcher implements Runnable {
List<Entry> watchList = new ArrayList<Entry>();
/*监控队列,判断线程是否alive,death则从队列中移除,执行回调,*/
@Override
public void run() {
for(;;) {
fetchWatchees();
notifyWatchees();
fetchWatchees();
notifyWatchees();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(watchList.isEmpty() && threadQueue.isEmpty()) {
started.compareAndSet(true, false);
if(threadQueue.isEmpty()) {
/*
* 1.待处理的队列已经为空
* 2.已经启动了新的线程去处理待处理线程了.*/
break;
}
/*1.已经有了待处理的线程了,需要判断是否已经有新的线程已经启动了,如果没有
* 当前线程继续处理,否则让新线程去处理.
* */
if(!started.compareAndSet(false, true)) {
break;
}
}
}
}
/**
*@desc
*@auth zhangwy @date 2017年2月21日 上午7:06:01
**/
private void fetchWatchees() {
for(;;) {
Entry entry = threadQueue.poll();
if(entry == null) {
break;
}
if(entry.isWatching) {
watchList.add(entry);
} else {
watchList.remove(entry);
}
}
}
/**
*@desc
*@auth zhangwy @date 2017年2月21日 上午7:06:04
**/
private void notifyWatchees() {
for(int i = 0; i < watchList.size(); ) {
Entry entry = watchList.get(i);
if(!entry.thread.isAlive()) {
watchList.remove(i);
try {
entry.task.run();
}catch (Exception e) {
e.printStackTrace();
}
} else {
i++;
}
}
}
}
}
class Entry {
Thread thread ;
Runnable task;
boolean isWatching;
Entry(Thread thread, Runnable task,boolean isWatching) {
this.thread = thread;
this.task = task;
this.isWatching = isWatching;
}
/*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return thread.hashCode() ^ task.hashCode();
}
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if(!(this instanceof Entry)) {
return false;
}
if(!(obj instanceof Entry)) {
return false;
}
Entry entry = (Entry)obj;
return this.thread == entry.thread && this.task == this.task;
}
}