線程狀態及各狀態下與鎖和CPU的關系


線程的狀態

Thread.State枚舉類型中定義了線程的六種狀態:NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED

線程在某一時刻只能擁有一種狀態,但是在線程的整個生命周期,線程的狀態會發生變化。

public enum State {
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
    }

各狀態的說明

NEW

NEW狀態是線程已經被創建,但還沒調用start()。此時的線程是不可運行的,CPU將不會為其分配時間。

RUNNABLE

當新創建的線程調用了start(),線程便進入了RUNNABLE狀態。
RUNNABLE狀態是指可以獲得CPU運行時間的狀態,如果線程在此狀態下,線程有兩種子狀態,一種是等待CPU時間,另一種是獲得了CPU時間在執行代碼。

BLOCKED

BLOCKED狀態是線程無法獲取對象鎖時的狀態。此狀態下線程會阻塞,當線程成功獲取到鎖,線程將切換為RUNNABLE狀態。
BLOCKED狀態無法獲得CPU運行時間。

WAITING

WAITING狀態是指是指線程在執行過程中,主動出讓自己CPU運行時間,讓其他線程先執行,自己等待其它線程的特定操作后再恢復執行。

TIMED_WAITING

TIMED_WAITINGWAITING狀態相似,TIMED_WAITING增加了時間限制,其實沒有外部信號,在等待時間超時后,線程也會恢復。

TERMINATED

TERMINATED是線程的終止態,當線程執行完自己的任務,或在執行任務中發生了異常,線程都會進入TERMINATED,表示線程已經到了生命周期的末尾。

下圖是關於線程間各狀態切換的過程及發生狀態切換的一些條件。
image

操作 操作前線程狀態 操作后線程狀態 是否出讓CPU時間 是否需要先持有對象鎖 是否釋放對象鎖
new Thread() NEW
Thread.start() NEW RUNNABLE
synchronized能得到對象鎖 RUNNABLE RUNNABLE
synchronized無法得到對象鎖 RUNNABLE BLOCKED
Thread.join() RUNNABLE WAITING
Thread.join(t) RUNNABLE TIMED_WAITING
Thread.sleep(t) RUNNABLE TIMED_WAITING
Object.wait() RUNNABLE WAITING
Object.wait(t) RUNNABLE TIMED_WAITING
Object.notify() / Object.notifyAll() RUNNABLE RUNNABLE
Lock.lock() RUNNABLE WAITING
Lock.tryLock(t) RUNNABLE TIMED_WAITING
LockSupport.park() RUNNABLE WAITING
LockSupport.parkNanos(t)/LockSupport.parkUntil(t) RUNNABLE TIMED_WAITING
執行結束/執行異常 RUNNABLE TERMINATED

以下是一些測試代碼,可以運行下清晰的了解到狀態。
各狀態切換測試:

public class ThreadStateTest {

    public static void main(String[] args){
        threadStateNew();

        workingThread();

        threadStateTerminate();

        threadBlockedByLock();

        threadBlockedBySynchronized();

        threadSleep();

        threadWait();

        threadTimedWait();
    }

    private static void threadStateNew(){
        System.out.println("--------------------------");
        System.out.print("Never Start Thread State:");
        Thread thread = new Thread(()->{

        }, "Thread Never Start");
        //print NEW
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }

    private static void workingThread(){
        System.out.println("--------------------------");
        Thread thread = new Thread(()->{
           for(int i=0; i<100; i++){
               doSomeElse();
           }
        });

        thread.start();

        doSomeElse();
        //print RUNNABLE
        System.out.println("Working Thread State:" + thread.getState());
        System.out.println("--------------------------");
    }

    private static void threadStateTerminate(){
        System.out.println("--------------------------");
        System.out.print("Finish Job Thread State:");
        Thread thread = new Thread(()->{

        }, "Thread Finish Job");
        thread.start();


        try {
            //Main Thread Will Wait util this thread finished job
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print TERMINATED
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }

    private static void threadBlockedByLock(){
        System.out.println("--------------------------");
        System.out.print("Thread State Blocked By Lock:");
        ReentrantLock lock = new ReentrantLock();
        Thread thread = new Thread(()->{
                lock.lock();
        }, "Blocked Thread");

        lock.lock();

        thread.start();

        doSomeElse();
        //print WAITING
        System.out.println(thread.getState());

        lock.unlock();
        System.out.println("--------------------------");
    }

    private static void threadBlockedBySynchronized(){
        System.out.println("--------------------------");
        System.out.print("Thread Blocked By Synchronized:");
        Thread thread = new Thread(()->{
            synchronized (ThreadStateTest.class){

            }
        }, "Blocked by Synchronized Thread");

        synchronized (ThreadStateTest.class){
            thread.start();
            doSomeElse();
            //print BLOCKED
            System.out.println(thread.getState());
        }
        System.out.println("--------------------------");
    }

    private static void threadSleep(){
        System.out.println("--------------------------");
        System.out.print("Sleeping Thread:");
        Thread thread = new Thread(()->{
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "Thread sleep");

        thread.start();
        doSomeElse();
        //print TIMED_WAITING
        System.out.println(thread.getState());
        System.out.println("--------------------------");
    }


    private static void threadWait(){
        System.out.println("--------------------------");
        System.out.print("Thread Waiting:");
        Object lock = new Object();
        Thread threadA = new Thread(()->{
            synchronized (lock){
                try {
                    lock.wait();

                    for(int i=0; i<100; i++){
                        doSomeElse();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "Thread Waiting");

        Thread threadB = new Thread(()->{
            synchronized (lock){
                //print WAITING
                System.out.println("Before Notify, Thread A State:" + threadA.getState());
                lock.notify();
                //print BLOCKED
                System.out.println("After Notify, Thread A State:" + threadA.getState());
            }
        });


        threadA.start();
        doSomeElse();
        threadB.start();

        try {
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print RUNNABLE
        System.out.println("After Thread B finish job, Thread A State:" + threadA.getState());
        System.out.println("--------------------------");
    }

    private static void threadTimedWait(){
        System.out.println("--------------------------");
        System.out.print("Thread Waiting:");
        Object lock = new Object();
        Thread threadA = new Thread(()->{
            synchronized (lock){
                try {
                    lock.wait(1000);

                    for(int i=0; i<100; i++){
                        doSomeElse();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "Thread Waiting");

        Thread threadB = new Thread(()->{
            synchronized (lock){
                //print TIMED_WAITING
                System.out.println("Before Notify, Thread A State:" + threadA.getState());
                lock.notify();
                //print BLOCKED
                System.out.println("After Notify, Thread A State:" + threadA.getState());
            }
        });


        threadA.start();
        doSomeElse();
        threadB.start();

        try {
            threadB.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //print RUNNABLE
        System.out.println("After Thread B finish job, Thread A State:" + threadA.getState());
        System.out.println("--------------------------");
    }
    /**
     * take some times, let the thread get cpu time
     */
    private static void doSomeElse(){
        double meanless = 0d;
        for(int i=0; i<10000; i++){
            meanless += Math.random();
        }
    }

}

CPU時間運行測試:

public class ThreadCPUTimeTest {

    public static void main(String[] args) {
        testBlockedThreadCPUTime();
    }

    protected static void testBlockedThreadCPUTime() {
        Object lock = new Object();

        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                doSomethingElse();
            }
        }, "ThreadA: Blocked because of synchronized");

        Thread threadB = new Thread(() -> {
            synchronized (lock) {
                try {
                    threadA.start();
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "ThreadB: With Monitor But Sleep");

        threadB.start();
        //Main Thread Executing Job
        for (int i = 0; i < 100000; i++) {
            doSomethingElse();
        }
    }

    private static void doSomethingElse() {
        double meanless = 0d;

        for (int i = 0; i < 10000; i++) {
            meanless += Math.random();
        }
    }
}

用VISUALVM可以統計CPU時間:
CPU運行時間.png

詳細代碼可以GitHub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM