1. 程式人生 > >Java粗淺認識-併發程式設計(二)

Java粗淺認識-併發程式設計(二)

執行緒狀態

執行緒狀態在windows,linux和android等OS中狀態都是不一致的,Java對執行緒狀態做了一個抽象。

在java中執行緒狀態由Thread內部內State表示

java.lang.Thread.State

These states are virtual machine states which do not reflect any operating system thread states.

這些執行緒狀態不等於任何作業系統的執行緒狀態

執行緒狀態有,NEW,RUNABLE,WATING,TIMED_WAITING,TERMINATED

NEW

A thread that has not yet started is in this state.

一個執行緒被new出來後,並沒有開始執行。

RUNNABLE

A thread executing in the Java virtual machine is in this state.

一個執行緒在JVM程序中執行的狀態。

BLOCKED

A thread that is blocked waiting for a monitor lock is in this state.

一個執行緒在等待monitor lock 進入的狀態。

WAITING

A thread that is waiting indefinitely for another thread to perform a particular action is in this state.

無限等待其他執行緒執行的狀態。

TIMED_WAITING

A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.

有限時間內等待其他執行緒執行的狀態

TERMINATED

A thread that has exited is in this state.

執行緒已經退出的狀態。

Java執行緒狀態例項

RUNNABLE

    public static void runnable() {
        Thread thread = new Thread(() -> {
            while (true) {
            }
        }, "Runnable 狀態的執行緒");
        thread.start();
    }

控制檯監控的狀態,簡史和管理控制檯通過(jconsole 監控工具檢視,和之前提到的jvisualvm類似,jvisualvm後出來,也可以用jstack <pid>檢視,jstack是命令列工具,三個監控工具,結果是一致的。)

runnable

BLOCKED

阻塞狀態例項,等待synchronized(class位元組碼層面的monitorenter)進入的狀態。

    public static void blocked() throws InterruptedException {
        final Object object = new Object();
        Thread runnableThread = new Thread(() -> {
            synchronized (object) {
                while (true) {

                }
            }
        }, "Runnable 狀態的執行緒");

        Thread blockedThread = new Thread(() -> {
            synchronized (object) {

            }
        }, "blocked 狀態的執行緒。");

        runnableThread.start();
        //等待runnable 執行緒已經啟動後再啟動blockedThread
        Thread.sleep(500);
        blockedThread.start();
    }

控制檯結果

blocked

WAITING

waiting狀態,在三種情況下可以出現,Object.wait,Thread.join,LockSupport.park

object.wait例項

這裡在object上呼叫wait()方法的前提是必須要synchronized()獲取鎖後,不然會拋錯,與之相對的釋放狀態就是object.notify()(隨機喚醒在object上監聽的一個執行緒,讓它獲取object的鎖)或object.notifyAll()(通知所有監聽在object物件上的執行緒,讓他們同時競爭,只有一個可以獲取object上的鎖),由於沒法喚醒指定的執行緒獲取object的鎖,所以,在java1.5就出現了Lock和Condition,後面會詳細講Lock。

    private static void waiting() throws InterruptedException {
        final Object object = new Object();
        Thread waitingThread = new Thread(() -> {
            synchronized (object) {
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }, "waiting 狀態的執行緒");
        waitingThread.start();
    }

監控情況

waiting

  thread.join例項

    private static void join() throws InterruptedException {
        Thread joinThread = new Thread(() -> {
            Thread runnableThread = new Thread(() -> {
                while (true) {

                }

            }, "runnable 執行緒.");
            runnableThread.start();
            try {
                runnableThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "等待join的執行緒 狀態的執行緒");
        joinThread.start();
    }

監控例項

runnable執行緒狀態

runnable

join執行緒狀態 

waiting

LockSupport.park例項

    private static void lockSupport() {
        new Thread(() -> {
            LockSupport.park();
        }, "lockSupport 執行緒。").start();
    }

 監控狀態

LockSupportPark

TIMED_WAITING

timed_waiting狀態有呼叫5個方法中的一種,就會出現,Thread.sleep,Object#wait(long) ,join(long) ,LockSupport#parkNanos ,LockSupport#parkUntil

thread.sleep

用的就比較多,我就不多說了,示例程式碼。提一點,TimeUnit.SECONDS.sleep(1000*60);這樣寫也是可以的

    private static void sleep() {
        new Thread(() -> {
            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "sleep 執行緒。").start();
    }

控制檯 

sleep

Object.wait(long)

物件毫秒等待

    private static void objectWait() {
        Object object = new Object();
        new Thread(() -> {
            synchronized (object) {
                try {
                    object.wait(1000 * 60);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "object.wait 執行緒。").start();
    }

監控

objectWait

Thread.join(long)

毫秒等待執行緒執行緒結束

   private static void timedJoin() throws InterruptedException {
        Thread joinThread = new Thread(() -> {
            Thread runnableThread = new Thread(() -> {
                while (true) {
                }

            }, "runnable 執行緒.");
            runnableThread.start();
            try {
                runnableThread.join(1000 * 60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "等待join的執行緒狀態的執行緒");
        joinThread.start();
    }

監控狀態

runnable執行緒狀態

runnable

join執行緒狀態 

join

LockSupport.parkNanos(long)

納秒時間等待,1000000000納秒=1秒在java中數值型別可以加下劃線在java1.5中的特性比如: int i = 1_00;double d = 1.00_01d;這樣寫是合法的,便於閱讀。

    private static void lockSupoortNanosObject() throws InterruptedException {
        final Object object = new Object();
        Thread lockSupportObjectThread = new Thread(() -> {
            //停頓60s
            LockSupport.parkNanos(object, 1000_000_000L * 60);
        }, "lockSupportObjectThread 執行緒");
        lockSupportObjectThread.start();
    }

監控狀態

lockSupportParkObject

LockSupport.parkUntil

等待絕對時間,直到什麼時刻為止,例項程式碼等待距現在60s

    private static void lockSupportParkUntil() {
        Thread thread = new Thread(()->{
            LockSupport.parkUntil(System.currentTimeMillis()+1000*60);
        },"lockSupportParkUtil 執行緒");
        thread.start();
    }

監控

LockSupport.parkUntil

總結

這一講主要對java的5中執行緒狀態做了例項說明,這裡需要注意一點小細節,在建立執行緒的時候,務必帶上名稱,方便監控,下一講,我們進入執行緒的使用,包括執行緒的狀態轉移。