Java併發(七)----線程sleep、yield、線程優先級

1、sleep 與 yield

sleep

  1. 調用 sleep 會讓當前線程從 Running 進入 Timed Waiting 狀態(阻塞)

  2. 其它線程可以使用 interrupt 方法打斷正在睡眠的線程,這時 sleep 方法會拋出 InterruptedException

  3. 睡眠結束後的線程未必會立刻得到執行

  4. 建議用 TimeUnit 的 sleep 代替 Thread 的 sleep 來獲得更好的可讀性(TimeUnit.SECONDS.sleep(1);)

調用sleep

    public static void main(String[] args) {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
​
        t1.start();
        log.debug("t1 state: {}", t1.getState());
​
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("t1 state: {}", t1.getState());
    }

輸出

22:23:02.365 c.Test6 [main] - t1 state: RUNNABLE
22:23:02.893 c.Test6 [main] - t1 state: TIMED_WAITING

調用interrupt

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                log.debug("enter sleep...");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    log.debug("wake up...");
                    e.printStackTrace();
                }
            }
        };
        t1.start();
​
        Thread.sleep(1000);
        log.debug("interrupt...");
        t1.interrupt();
    }

輸出

22:26:48.155 c.Test7 [t1] - enter sleep...
22:26:49.158 c.Test7 [main] - interrupt...
22:26:49.158 c.Test7 [t1] - wake up...
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at cn.itcast.test.Test7$1.run(Test7.java:14)

yield

  1. 調用 yield 會讓當前線程從 Running 進入 Runnable 就緒狀態,然後調度執行其它線程,注意:如果沒有其他線程的話,可能還是執行當前線程

  2. 具體的實現依賴於操作系統的任務調度器

2、sleep yield區別

共同點:

1.都是Thread類中的類方法

2.都會導致正在執行的線程釋放CPU

區別:

1.線程進入的狀態不同:sleep方法導致線程進入到阻塞狀態,yield方法導致線程進入就緒狀態

2.是否考慮線程優先級:sleep方法不會考慮線程優先級,當一個線程調用sleep方法釋放CPU後,所有優先級級別的線程都有機會獲得CPU。yield方法會考慮線程優先級。當一個線程調用sleep方法釋放CPU後,與該線程具有同等優先級,或優先級比該線程高的線程有機會獲得CPU

3.可移植性:sleep方法比yield方法具有更好的可移植性

4.是否拋出異常:sleep方法聲明拋出InterruptedException,而yield方法沒有聲明任何異常

5.是否有參數:sleep方法在Thread類中有兩種重載形式,sleep(long ms),sleep(long ms,int nanos)yield方法沒有參數

 

3、線程優先級

  • 線程優先級會提示(hint)調度器優先調度該線程,但它僅僅是一個提示,調度器可以忽略它

  • 如果 cpu 比較忙,那麼優先級高的線程會獲得更多的時間片,但 cpu 閒時,優先級幾乎沒作用

所以不一定優先級設置高就一定能有限執行,具體執行依賴任務調度器。

Runnable task1 = () -> {
    int count = 0;
    for (;;) {
        System.out.println("---->1 " + count++);
    }
};
Runnable task2 = () -> {
    int count = 0;
    for (;;) {
        // Thread.yield();
        System.out.println("              ---->2 " + count++);
    }
};
Thread t1 = new Thread(task1, "t1");
Thread t2 = new Thread(task2, "t2");
// t1.setPriority(Thread.MIN_PRIORITY);
// t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();

這裏讀者可將註釋去掉自行實踐,即可體會yield與優先級的使用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章