概述
java.lang.Thread類包含一個靜态State枚舉,定義了線程的狀态。在任何給定的時間點,線程隻能處于以下狀态之一:
- NEW:尚未開始執行的新建立的線程
- RUNNABLE:正在運作或準備執行,但正在等待資源配置設定
- BLOCKED:等待擷取螢幕鎖以進入或重新進入同步塊/方法
- WAITING:等待其他線程執行特定操作,沒有任何時間限制
- TIMED_WAITING:等待其他線程在指定的時間段内執行特定操作
- TERMINATED:已完成執行
NEW
一個已經建立但尚未啟動的線程,一直保持NEW這種狀态,直到使用start()方法啟動。
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
System.out.println(t.getState());
方法t.getState()将列印:
NEW
RUNNABLE
建立了一個新線程并調用了該線程的start()方法時,狀态就從NEW轉變為RUNNABLE。處于RUNNABLE狀态的線程正在運作或準備運作,但它們正在等待系統的資源配置設定。
在多線程環境中,線程排程器(JVM的一部分)為每個線程配置設定固定的時間。是以,該線程會運作一段特定的時間,然後将控制權交給其他RUNNABLE線程。
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
t.start();
System.out.println(t.getState());
RUNNABLE
BLOCKED
當線程正在等待螢幕鎖并試圖通路被其他線程鎖定的代碼段時,會進入BLOCKED狀态。
public class BlockedState {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new DemoBlockedRunnable());
Thread t2 = new Thread(new DemoBlockedRunnable());
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println(t2.getState());
System.exit(0);
}
}
class DemoBlockedRunnable implements Runnable {
@Override
public void run() {
commonResource();
}
public static synchronized void commonResource() {
while(true) {
// Infinite loop to mimic heavy processing
// 't1' won't leave this method
// when 't2' try to enter this
}
}
}
- 建立了兩個不同的線程:t1和t2;
- t1啟動并進入synchronized commonResource()方法;這意味着隻有一個線程可以通路它;嘗試通路此方法的所有其他後續線程将被阻止進一步執行,直到目前線程完成處理;
- 當t1進入這個方法時,它保持在一個無限while循環中;這隻是為了模拟有耗時長的業務處理,使所有其他線程都無法進入該方法;
- 當啟動t2時,它試圖進入commonResource()方法,t1已經在通路該方法,是以,t2将保持在BLOCKED狀态
調用t2.getState()将輸出:
BLOCKED
WAITING
線程在等待其他線程執行特定操作時處于WAITING狀态。任何線程都可以通過調用以下三種方法進入這種狀态:
- object.wait()
- thread.join()
- LockSupport.park()
public class WaitingState implements Runnable {
public static Thread t1;
public static void main(String[] args) {
t1 = new Thread(new WaitingState());
t1.start();
}
public void run() {
Thread t2 = new Thread(new DemoWaitingStateRunnable());
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
class DemoWaitingStateRunnable implements Runnable {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println(WaitingState.t1.getState());
}
}
- 建立并啟動了t1
- t1建立一個t2并啟動它
- 當t2的處理繼續時,我們調用t2.join(),這将使t1處于WAITING狀态,直到t2完成執行
由于t1正在等待t2完成,是以我們從t2調用t1.getState():
WAITING
TIMED_WAITING
當線程在規定的時間内等待另一個線程執行特定操作時,它處于TIMED_WAITING狀态。
- thread.sleep(long millis)
- wait(int timeout) 或 wait(int timeout, int nanos)
- thread.join(long millis)
- LockSupport.parkNanos
- LockSupport.parkUntil
public class TimedWaitingState {
public static void main(String[] args) throws InterruptedException {
DemoTimeWaitingRunnable runnable= new DemoTimeWaitingRunnable();
Thread t1 = new Thread(runnable);
t1.start();
// The following sleep will give enough time for ThreadScheduler
// to start processing of thread t1
Thread.sleep(1000);
System.out.println(t1.getState());
}
}
class DemoTimeWaitingRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
}
建立并啟動了一個線程t1,該線程進入睡眠狀态,逾時時間為5秒;t1.getState()輸出:
TIMED_WAITING
TERMINATED
線程完成執行或異常終止時,它處于TERMINATED狀态。
public class TerminatedState implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new TerminatedState());
t1.start();
// The following sleep method will give enough time for
// thread t1 to complete
Thread.sleep(1000);
System.out.println(t1.getState());
}
@Override
public void run() {
// No processing in this block
}
}
啟動線程t1時,語句thread.sleep(1000)是為t1提供了足夠的時間來完成,是以輸出如下:
TERMINATED
結論
了解Java中線程的生命周期,及狀态轉化的原因,是定位多線程問題的前提,也可以通過ThreadDump實時檢視到目前所有線程的執行狀态。