天天看點

并發(十):用一個類實作周遊線程的所有狀态

在Thread中,有一個關于線程狀态的枚舉類Thread.State,其共有六個狀态,分别為:

1. NEW, 線程未啟動;

2. RUNNABLE,線程正在運作中;

3. BLOCKED, 線程因為等待鎖被阻塞;

4. WAITING,線程處于等待(信号)狀态中;

5. TIMED_WAITING,主動調用了限時等待方法而處于等待狀态中;

6. TERMINATED,線程已結束;

下面我們用一個類來周遊線程的所有狀态:

public class ThreadStateTest extends Thread {

    //  同步鎖1
    private static Object monitorA = new Object();

    //  同步鎖2
    private static Object monitorB = new Object();

    //  進入條件
    private static volatile boolean locked = false;

    public void run() {
        //  一旦啟動,将會進入RUNNABLE狀态
        System.out.println("2:" + this.getState());
        synchronized (monitorA) {
            try {
                //  3:此時探測,将會處于TIMED_WAITING狀态
                Thread.sleep();
                //4:等待鎖,處于BLOCKED狀态;
                synchronized (monitorB) {
                    while(!locked) {
                        //  5: 等待信号,處于WAITING狀态
                        monitorB.wait();
                    }                   
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {        
        Thread th = new ThreadStateTest();
        //  未啟動,NEW狀态
        System.out.println("1: " + th.getState());
        th.start();
        //  啟動額外的線程,用于觀測線程的狀态變化
        new Thread() {
            public void run() {
                synchronized (monitorB) {
                    System.out.println("3:" + th.getState());
                    while(th.getState() != Thread.State.BLOCKED) {
                        Thread.yield();
                    }
                    System.out.println("4:" + th.getState());
                }               
                while(th.getState() != Thread.State.WAITING) {
                    Thread.yield();
                }
                System.out.println("5:" + th.getState());
                //  發信号通知線程激活
                synchronized (monitorB) {
                    locked = true;
                    monitorB.notify();
                }
            }           
        }.start();
        //  等待線程結束,擷取線程的終結狀态
        th.join();
        System.out.println("6:" + th.getState());
    }

}
           

最後的輸入結果如下,六個狀态一個不少:

: NEW
:RUNNABLE
:TIMED_WAITING
:BLOCKED
:WAITING
:TERMINATED
           

總結

  1. BLOCKED與WAITING狀态的差別:
    BLOCKED狀态用于等待鎖的進入,WAITING狀态是因為主動調用了notify、join方法,而待線程信号的通知。
  2. TIMED_WAITING與WAITING的差別:
    除了notify、join方法(有限制時間)能讓線程進入TIMED_WAITING狀态,sleep方法也可以,參見上例中的狀态3。