官术网_书友最值得收藏!

1.5 讓線程睡眠的sleep方法

Thread類中有一個靜態的sleep方法,當一個執行中的線程調用了Thread的sleep方法后,調用線程會暫時讓出指定時間的執行權,也就是在這期間不參與CPU的調度,但是該線程所擁有的監視器資源,比如鎖還是持有不讓出的。指定的睡眠時間到了后該函數會正常返回,線程就處于就緒狀態,然后參與CPU的調度,獲取到CPU資源后就可以繼續運行了。如果在睡眠期間其他線程調用了該線程的interrupt()方法中斷了該線程,則該線程會在調用sleep方法的地方拋出InterruptedException異常而返回。

下面舉一個例子來說明,線程在睡眠時擁有的監視器資源不會被釋放。

public class SleepTest2 {
    // 創建一個獨占鎖
    private static final Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        // 創建線程A
        Thread threadA = new Thread(new Runnable() {
            public void run() {
                // 獲取獨占鎖
                lock.lock();
                try {
                    System.out.println("child threadA is in sleep");
                    Thread.sleep(10000);
                    System.out.println("child threadA is in awaked");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 釋放鎖
                    lock.unlock();
                }
            }
        });
        // 創建線程B
        Thread threadB = new Thread(new Runnable() {
            public void run() {
                // 獲取獨占鎖
                lock.lock();
                try {
                    System.out.println("child threadB is in sleep");
                    Thread.sleep(10000);
                    System.out.println("child threadB is in awaked");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 釋放鎖
                    lock.unlock();
                }
            }
        });
        // 啟動線程
        threadA.start();
        threadB.start();
    }
}

執行結果如下。

如上代碼首先創建了一個獨占鎖,然后創建了兩個線程,每個線程在內部先獲取鎖,然后睡眠,睡眠結束后會釋放鎖。首先,無論你執行多少遍上面的代碼都是線程A先輸出或者線程B先輸出,不會出現線程A和線程B交叉輸出的情況。從執行結果來看,線程A先獲取了鎖,那么線程A會先輸出一行,然后調用sleep方法讓自己睡眠10s,在線程A睡眠的這10s內那個獨占鎖lock還是線程A自己持有,線程B會一直阻塞直到線程A醒來后執行unlock釋放鎖。下面再來看一下,當一個線程處于睡眠狀態時,如果另外一個線程中斷了它,會不會在調用sleep方法處拋出異常。

public static void main(String[] args) throws InterruptedException {
        //創建線程
        Thread thread = new Thread(new  Runnable() {
            public void run() {
                try {
                    System.out.println("child thread is in sleep");
                    Thread.sleep(10000);
                    System.out.println("child thread is in awaked");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //啟動線程
        thread.start();
        //主線程休眠2s
        Thread.sleep(2000);
        //主線程中斷子線程
        thread.interrupt();
    }

執行結果如下。

子線程在睡眠期間,主線程中斷了它,所以子線程在調用sleep方法處拋出了InterruptedException異常。

另外需要注意的是,如果在調用Thread.sleep(long millis)時為millis參數傳遞了一個負數,則會拋出IllegalArgumentException異常,如下所示。

主站蜘蛛池模板: 鄂托克前旗| 阳高县| 仲巴县| 通渭县| 高密市| 越西县| 芜湖市| 花莲市| 深州市| 定陶县| 新竹市| 科尔| 台北市| 成安县| 汾阳市| 大同市| 积石山| 锡林郭勒盟| 云和县| 育儿| 太仆寺旗| 江都市| 武城县| 成都市| 麟游县| 和政县| 三亚市| 岱山县| 张家川| 岳阳市| 旌德县| 石楼县| 德州市| 灵武市| 巴南区| 永川市| 房产| 昌乐县| 湛江市| 茂名市| 文昌市|