这次这个的思路是在主类中维护一个map,map的key是线程名,value是线程的状态,然后创建周期执行的线程通过检测这个map来判断进程的状态,如果有死亡的进程就把该进程启动。
首先是主类,这里的main方法中为了执行结果简单易懂 ,先是初始化了一个长度为2的newFixedThreadPool线程池,然后提交了2个任务(这个任务类下面会有介绍),然后启动监控线程,这个监控线程也是一会介绍,其他方法的作用注释写得也很清楚:
public classTest {/**Log4j 初始化*/
private static final Logger logger = LoggerFactory.getLogger(Test.class);/**标志线程存活的变量*/
public static final int THREAD_STATUS_ALIVE = 1;/**标志线程死亡的变量*/
public static final int THREAD_STATUS_DEAD = 0;/**记录每个线程的状态的map*/
private static HashMap threadStatesMap = new HashMap();/**线程池的长度*/
private static intthreadPoolLength;/**创建固定长度的线程池*/
private staticExecutorService executor;public static voidmain(String[] args) {/**初始化线程池*/executor= Executors.newFixedThreadPool(2);/**提交Task给线程池*/
for(int i = 1; i <= 2; i++){
executeToPool(newEtlTask(i));
}
Monitor monitor= newMonitor();/**启动检测线程*/monitor.start();
}/*** 根据线程名,更新线程的状态
*@paramthreadName
*@paramstatus*/
public synchronized static voidalterThreadStatesMap(String threadName,Integer status){
threadStatesMap.put(threadName,status);
}/*** 返回ThreadStatesMap的长度
*@return
*/
public static intgetThreadStatesMapSize(){returnthreadStatesMap.size();
}/*** 返回key对应ThreadStatesMap的value
*@paramkey
*@returnThreadStatesMapValueByKey*/
public static intgetThreadStatesMapValueByKey(String key){returnthreadStatesMap.get(key);
}/*** 提交任务给线程池
*@parametlTask*/
public static voidexecuteToPool(EtlTask etlTask){
executor.execute(etlTask);
}
}
然后创建一个会报异常的测试类(id每一秒减一次1,到0的时候抛异常):
/*** 测试线程*/
classtestThread {private static Logger logger = LoggerFactory.getLogger(testThread.class);public static void start(int id) throwsException{
id= id + 5;while (true){try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
id= id - 1;if(id == 0){//id每一秒减一次1,到0的时候抛异常
throw newException();
}
logger.debug(Thread.currentThread().getName()+ " is running result = " +id );
}
}
}
然后创建一个执行上面测试任务的任务类,这里在第一次被启动的时候会设置好该任务类的名字,将主类中的map中线程名对应的value设置为THREAD_STATUS_ALIVE,然后开始执行上面的测试任务,如果有异常的话会将主类中的map中线程名对应的value设置为THREAD_STATUS_DEAD:
/*** 任务线程*/
class EtlTask implementsRunnable{/**组ID*/
private intgroupid ;/**初始化组ID*/EtlTask(intgroupid){this.groupid =groupid;
}public voidrun() {/**设置线程名*/Thread.currentThread().setName("G" +groupid);/**设置线程的 运行状态为THREAD_STATUS_ALIVE 在ThreadStatesMap中*/Test.alterThreadStatesMap(Thread.currentThread().getName(),Test.THREAD_STATUS_ALIVE);try{/**将组ID传入,执行任务*/
testThread.start(groupid);
}catch(Exception e ){/**出现异常 设置线程的 运行状态为THREAD_STATUS_DEAD 在ThreadStatesMap中*/Test.alterThreadStatesMap(Thread.currentThread().getName(),Test.THREAD_STATUS_DEAD);
}
}
}
最后就是监控类,这个类就是在遍历主类中的map,有死亡的线程就启动该线程。
/*** 监控线程*/
class Monitor extendsThread{private static final Logger logger = LoggerFactory.getLogger(Monitor.class);public voidrun() {while(true){try{
Thread.sleep(5000);//监控线程阻塞5秒后运行
}catch(Exception e){
e.printStackTrace();
}
logger.debug("Current total [" + Test.getThreadStatesMapSize() +"] threads");/**线程存活数*/
int alives = 0;/**线程死亡数*/
int deads = 0;/**遍历ThreadStatesMap 计算线程存活数和死亡数*/
for(int i = 1;i <= Test.getThreadStatesMapSize();i++){if(Test.getThreadStatesMapValueByKey("G" + i) ==Test.THREAD_STATUS_ALIVE){
alives++;
}else{
deads++;
}
}
logger.debug("Current the number of threads alive is [" + alives +"]");
logger.debug("Current the number of threads dead is [" + deads +"]");/**如果死亡线程数大于0 就启动已经死亡的线程*/
if(deads > 0) {/**遍历ThreadStatesMap 将死亡的线程启动*/
for (int i = 1; i <= Test.getThreadStatesMapSize(); i++) {if (Test.getThreadStatesMapValueByKey("G" + i) ==Test.THREAD_STATUS_DEAD) {/**向线程池提交任务*/Test.executeToPool(newEtlTask(i));
logger.debug("Thread G" + i + "已被启动");
}
}
}
}
}
}
效果:
2018-08-02 16:24:31,649 - G2 is running result = 6
2018-08-02 16:24:31,655 - G1 is running result = 5
2018-08-02 16:24:32,653 - G2 is running result = 5
2018-08-02 16:24:32,656 - G1 is running result = 4
2018-08-02 16:24:33,653 - G2 is running result = 4
2018-08-02 16:24:33,656 - G1 is running result = 3
2018-08-02 16:24:34,653 - G2 is running result = 3
2018-08-02 16:24:34,656 - G1 is running result = 2
2018-08-02 16:24:35,635 - Current total [2] threads2018-08-02 16:24:35,635 - Current the number of threads alive is [2]2018-08-02 16:24:35,635 - Current the number of threads dead is [0]2018-08-02 16:24:35,654 - G2 is running result = 2
2018-08-02 16:24:35,657 - G1 is running result = 1
2018-08-02 16:24:36,654 - G2 is running result = 1
2018-08-02 16:24:40,635 - Current total [2] threads2018-08-02 16:24:40,635 - Current the number of threads alive is [0]2018-08-02 16:24:40,635 - Current the number of threads dead is [2]2018-08-02 16:24:40,635 -Thread G1已被启动2018-08-02 16:24:40,635 -Thread G2已被启动2018-08-02 16:24:41,635 - G2 is running result = 6
2018-08-02 16:24:41,635 - G1 is running result = 5
2018-08-02 16:24:42,636 - G1 is running result = 4
2018-08-02 16:24:42,636 - G2 is running result = 5
2018-08-02 16:24:43,636 - G2 is running result = 4
2018-08-02 16:24:43,636 - G1 is running result = 3
2018-08-02 16:24:44,637 - G2 is running result = 3
2018-08-02 16:24:44,637 - G1 is running result = 2
2018-08-02 16:24:45,636 - Current total [2] threads2018-08-02 16:24:45,636 - Current the number of threads alive is [2]2018-08-02 16:24:45,636 - Current the number of threads dead is [0]2018-08-02 16:24:45,637 - G1 is running result = 1
2018-08-02 16:24:45,637 - G2 is running result = 2
2018-08-02 16:24:46,637 - G2 is running result = 1
2018-08-02 16:24:50,636 - Current total [2] threads2018-08-02 16:24:50,636 - Current the number of threads alive is [0]2018-08-02 16:24:50,636 - Current the number of threads dead is [2]2018-08-02 16:24:50,636 -Thread G1已被启动2018-08-02 16:24:50,636 -Thread G2已被启动2018-08-02 16:24:51,637 - G2 is running result = 6
2018-08-02 16:24:51,637 - G1 is running result = 5
2018-08-02 16:24:52,637 - G1 is running result = 4
2018-08-02 16:24:52,637 - G2 is running result = 5Process finished with exit code-1
从控制台的输出日志可以看到,两个线程的结果到0的时候死亡了,然后会被监控进程启动。