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是命令列工具,三個監控工具,結果是一致的。)
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();
}
控制檯結果
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();
}
監控情況
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執行緒狀態
join執行緒狀態
LockSupport.park例項
private static void lockSupport() {
new Thread(() -> {
LockSupport.park();
}, "lockSupport 執行緒。").start();
}
監控狀態
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();
}
控制檯
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();
}
監控
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執行緒狀態
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();
}
監控狀態
LockSupport.parkUntil
等待絕對時間,直到什麼時刻為止,例項程式碼等待距現在60s
private static void lockSupportParkUntil() {
Thread thread = new Thread(()->{
LockSupport.parkUntil(System.currentTimeMillis()+1000*60);
},"lockSupportParkUtil 執行緒");
thread.start();
}
監控
總結
這一講主要對java的5中執行緒狀態做了例項說明,這裡需要注意一點小細節,在建立執行緒的時候,務必帶上名稱,方便監控,下一講,我們進入執行緒的使用,包括執行緒的狀態轉移。