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的时候死亡了,然后会被监控进程启动。

  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/xxbbtt/p/9407923.html
Copyright © 2011-2022 走看看