(一)線程管理_4---線程休眠和恢復

線程休眠和恢復

在有的時候需要將線程暫時停止執行,在一段時間後恢復線程,讓其繼續執行;比如一個線程每隔一分鐘執行一次狀態檢查,那麼餘下的時間我們希望它能夠讓出CPU time,什麼也不做,最大的減少資源的浪費;在線程恢復後,再給予CPU time,讓其繼續執行;爲了滿足這樣一個需求,可以調用Thread類的sleep()方法達到這個目的;

Thread.sleep(millis) ,另外還可以使用TimeUnit類進行休眠,如TimeUnit.SECONDS.sleep(millis) ;

動手實驗

public class FileClock implements Runnable{
    @Override
    public void run() {
        /*
            每次循環打印一個時間,模擬一個任務,之後休眠1毫秒,
            在sleep時,如果被中斷,將會拋出InterruptedException
         */
        for (int i = 0; i < 10; i++) {
            System.out.printf("%s\n",new Date());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.printf("The FileClock has been interrupted.");
            }
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new FileClock());
        thread.start();

        /*
            主線程等待5毫秒
         */
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /*
            喚醒FileClock線程
         */
        thread.interrupt();
    }
}

一次運行結果:

Thu Oct 30 23:09:25 CST 2014
Thu Oct 30 23:09:26 CST 2014
Thu Oct 30 23:09:27 CST 2014
Thu Oct 30 23:09:28 CST 2014
Thu Oct 30 23:09:29 CST 2014
The FileClock has been interrupted.Thu Oct 30 23:09:30 CST 2014
Thu Oct 30 23:09:31 CST 2014
Thu Oct 30 23:09:32 CST 2014
Thu Oct 30 23:09:33 CST 2014
Thu Oct 30 23:09:34 CST 2014


首先,fileclock線程開始執行,然後主線程等待,在fileclock還沒結束,主線程執行對fileclock執行了interrupt()方法,注意這裏,上節記錄的這個方法會有effect以及它和IsInterrupt的區別,這個方法設置線程的中斷標記,那麼此時有一個問題:如果此時fileclock剛還沒有進入sleep方法,此時該怎麼執行?會不會當再次進入sleep時直接中斷進入catch塊,還是執行休眠完後中斷? 如果此時fileclock線程正在休眠,顯然會直接中斷被catch塊捕獲,這個就毫無疑問了,那麼下面就上面這個疑惑進行一個實驗,主線程啓動子線程後,調用interrupt,設置子線程已經中斷,故意讓子線程一定在主線程執行了interrupt之後,子線程才調用sleep,已觀察執行過程,那麼下面開始

public class InterruptTest implements Runnable{
    @Override
    public void run() {
        /*
            while的目的是保證在主線執行完thread.interrupt()方法後,才結束while
            執行下面的sleep,可以通過結果的兩個輸出看出(Before,After)
         */
        long start=System.currentTimeMillis();
        while((System.currentTimeMillis()-start)<5000){
            //empty
        }
        System.out.printf("After:Thread will be sleep.\n");
        try {
            TimeUnit.SECONDS.sleep(200);
            System.out.printf("After sleep.\n");
        } catch (InterruptedException e) {
            System.out.printf("Interrupted.");
        }
    }

    public static void main(String[] args) {
        Thread thread = new Thread(new InterruptTest());
        thread.start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        thread.interrupt();
        System.out.printf("Before:Main execute thread.interrupt().\n");
    }
}
執行結果:

Before:Main execute thread.interrupt().
After:Thread will be sleep.
Interrupted.

顯然 sleep語句後面的“After sleep"並沒有輸出,從輸出的結果可以看到子線程也並沒有去休眠200毫秒,而至直接中斷被catch捕獲;

那麼可以得出結論:當一個線程的被設置了中斷狀態,如調用了interrupt(),那麼該線程在執行到sleep時,將會立即被中斷捕獲;


要點

還是要理解線程維護的中斷狀態和Thread.interrupt()之後線程如何執行;

此外 Thread.yield()方法也能是線程暫時放棄cpu,但是JVM並不保證線程的這個請求的響應;通常,僅僅是作爲debug的目的;


發佈了61 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章