天天看點

Java線程排程&狀态

摘要

  1. 什麼是線程排程
  2. 協同式排程
  3. 搶占式排程
  4. 線程優先級
  5. 線程狀态

1. 線程排程

1.1 什麼是線程排程

線程排程是指系統為線程配置設定處理器使用權的過程。

1.2 協同式排程

線程的執行時間由線程本身控制,線程在工作完成以後要主動通知系統切換到另一個線程上。優點是實作簡單、切換操作對線程自己可見,不存線上程同步問題;缺點是線程時間不可控制,有可能造成程式一直阻塞。

1.2 搶占式排程

線程由作業系統來配置設定執行時間,線程的切換不會由線程本身決定。優點是線程執行時間可控;缺點則是需要進行線程同步。

Java中的線程采用的是搶占式排程的實作方式。

2. 線程優先級

線程優先級是用來表示線程獲得CPU資源的可能性,線程優先級越高,系統更容易為其配置設定處理器去執行。

Java中的線程優先級不太靠譜,原因是Java定義了大約10個級别的優先級,最小的優先級為1,最高優先級為10,線程的優先級預設與父線程一緻,假設作業系統線程的優先級的級别層次比Java少(最小1,最大5),那麼在映射以後,Java兩個不同優先級的優先級有可能共同對應作業系統的同一個優先級。

3. 線程狀态

Java線程大緻有以下狀态:

  1. New
  2. Runnable
  3. Waiting
  4. TimeWaiting
  5. Blocked
  6. Terminated
Java線程排程&狀态

3.1 New

建立以後尚未啟動的線程,new但未start。

3.2 Runnable

Runnable的線程有可能在執行,也有可能等待着CPU為它配置設定執行時間。

3.3 Waiting

線程不會被CPU配置設定執行時間,需要其他線程顯示喚醒。以下方法會讓線程進入Waiting狀态:

  • 沒有Timeout的Object.wait()
  • 沒有Timeout的Thread.join()
  • LockSupport.park()方法

3.4 TimeWaiting

線程不會被CPU配置設定執行時間,可以被其他線程顯示喚醒,一定時間後沒有其他線程喚醒,将會由作業系統主動喚醒。以下方法會讓線程進入TimeWaiting狀态:

  • Thread.sleep()
  • 設定了Timeout的Object.wait()
  • 設定了Timeout的Thread.join()
  • LockSupport.parkNanos()
  • LockSupport.parkUntil()

3.5 Blocked

線程處于阻塞狀态,阻塞狀态的線程在等待着擷取到一個排他鎖。在程式等待進入同步區域的時候,線程将進入這種狀态

3.6 Terminate

線程執行結束以後的狀态。

package jvm;

/**
 * @author sh
 */
public class ThreadTest implements Runnable {


    @Override
    public void run() {
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest, "TEST-1");
        thread.start();
        thread.join();
    }
}           

複制

上述代碼首先根據前文我們的描述,我們可以得出,主線程應該是Waiting(由于Thread.join()方法的調用),TEST-1線程應該是TimeWaiting狀态(通過Thread.sleep()方法的調用)。

下面我們通過jstack指令看一下我們的堆棧是不是和我們分析的結果一緻:

Java線程排程&狀态
Java線程排程&狀态
public class ThreadTest implements Runnable {

    private final Object syncObj = new Object();


    @Override
    public void run() {
        synchronized (syncObj) {
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = new Thread(threadTest, "TEST-1");
        Thread t2 = new Thread(threadTest, "TEST-2");
        t1.start();
        Thread.sleep(1L);
        t2.start();
        t1.join();
    }
}           

複制

上述這段代碼,TEST-1線程應該是TimeWaiting,TEST-2線程應該是BLOCK狀态,主線是Waiting狀态,下面我們通過jstack指令來看一下:

Java線程排程&狀态
Java線程排程&狀态

本期的Java線程排程和狀态實作介紹到這,我是shysh95,關注+在看+贊,你就是最靓的仔,我們下期再見!!

往期推薦

Java線程實作

Java記憶體模型(可見性有序性)

Java記憶體模型

Java學習路線

JIT即時編譯器(C1和C2)