Java——检测其他线程的状态以及启动已死亡的线程

这次这个的思路是在主类中维护一个map,map的key是线程名,value是线程的状态,然后创建周期执行的线程通过检测这个map来判断进程的状态,如果有死亡的进程就把该进程启动。

首先是主类,这里的main方法中为了执行结果简单易懂 ,先是初始化了一个长度为2的newFixedThreadPool线程池,然后提交了2个任务(这个任务类下面会有介绍),然后启动监控线程,这个监控线程也是一会介绍,其他方法的作用注释写得也很清楚:

public class Test {
    /** 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<String,Integer> threadStatesMap = new HashMap<String, Integer>();
    /** 线程池的长度*/
    private static int threadPoolLength;
    /** 创建固定长度的线程池 */
    private static ExecutorService executor;

    public static void main(String[] args) {
        /** 初始化线程池 */
        executor = Executors.newFixedThreadPool(2);
        /** 提交Task给线程池 */
        for(int i = 1; i <= 2; i++){
            executeToPool(new EtlTask(i));
        }
        Monitor monitor = new Monitor();
        /** 启动检测线程 */
        monitor.start();
    }
    /**
     * 根据线程名,更新线程的状态
     * @param threadName
     * @param status
     */
    public synchronized static void alterThreadStatesMap(String threadName,Integer status){
        threadStatesMap.put(threadName,status);
    }
    /**
     * 返回ThreadStatesMap的长度
     * @return
     */
    public static int getThreadStatesMapSize(){
        return threadStatesMap.size();
    }
    /**
     * 返回key对应ThreadStatesMap的value
     * @param key
     * @return ThreadStatesMapValueByKey
     */
    public static int getThreadStatesMapValueByKey(String key){
        return threadStatesMap.get(key);
    }
    /**
     * 提交任务给线程池
     * @param etlTask
     */
    public static void executeToPool(EtlTask etlTask){
        executor.execute(etlTask);
    }
}

然后创建一个会报异常的测试类(id每一秒减一次1,到0的时候抛异常):

/**
 * 测试线程
 */
class testThread {
    private static Logger logger = LoggerFactory.getLogger(testThread.class);
    public static void start(int id) throws Exception{
        id = id + 5;
        while (true){
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
           id =  id - 1;
           if(id == 0){
               //id每一秒减一次1,到0的时候抛异常
               throw new Exception();
           }
           logger.debug(Thread.currentThread().getName() + "  is running result = " + id );
        }

    }
}    

然后创建一个执行上面测试任务的任务类,这里在第一次被启动的时候会设置好该任务类的名字,将主类中的map中线程名对应的value设置为THREAD_STATUS_ALIVE,然后开始执行上面的测试任务,如果有异常的话会将主类中的map中线程名对应的value设置为THREAD_STATUS_DEAD:

/**
 * 任务线程
 */
 class EtlTask implements Runnable{
    /** 组ID */
    private int groupid ;
    /** 初始化组ID */
     EtlTask(int groupid){
         this.groupid = groupid;
    }
    public void run() {
        /** 设置线程名 */
        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 extends Thread{
    private static final Logger logger = LoggerFactory.getLogger(Monitor.class);
    public void run() {
        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(new EtlTask(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] threads
2018-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] threads
2018-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] threads
2018-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] threads
2018-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 = 5

Process finished with exit code -1

从控制台的输出日志可以看到,两个线程的结果到0的时候死亡了,然后会被监控进程启动。

原文地址:https://www.cnblogs.com/xxbbtt/p/9407923.html