zoukankan      html  css  js  c++  java
  • 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的时候死亡了,然后会被监控进程启动。

  • 相关阅读:
    第27课二阶构造模式(上)---------出现的背景
    第26课 静态成员函数
    第25课类的静态成员变量
    第24课经典问题解析(下)--------类的成员函数和成员变量隶属某个具体对象吗
    第24课经典问题(中)-----关于const对象的疑问
    第24课经典的问题(上)---------对象的构造顺序与析构顺序
    第23课 神秘的临时对象
    断剑重铸007
    DG on Windows 10 S: 执行任意代码
    断剑重铸006
  • 原文地址:https://www.cnblogs.com/xxbbtt/p/9407923.html
Copyright © 2011-2022 走看看