Java——檢測其餘線程的狀態以及啓動已死亡的線程

此次這個的思路是在主類中維護一個map,map的key是線程名,value是線程的狀態,而後建立週期執行的線程經過檢測這個map來判斷進程的狀態,若是有死亡的進程就把該進程啓動。測試

首先是主類,這裏的main方法中爲了執行結果簡單易懂 ,先是初始化了一個長度爲2的newFixedThreadPool線程池,而後提交了2個任務(這個任務類下面會有介紹),而後啓動監控線程,這個監控線程也是一會介紹,其餘方法的做用註釋寫得也很清楚:this

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的時候拋異常):spa

/**
 * 測試線程
 */
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,有死亡的線程就啓動該線程。debug

/**
 * 監控線程
 */
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的時候死亡了,而後會被監控進程啓動。code

相關文章
相關標籤/搜索