線程的狀態
Thread.State
枚舉類型中定義了線程的六種狀態:NEW
,RUNNABLE
,BLOCKED
,WAITING
,TIMED_WAITING
和TERMINATED
。
線程在某一時刻只能擁有一種狀態,但是在線程的整個生命周期,線程的狀態會發生變化。
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_WAITING
和WAITING
狀態相似,TIMED_WAITING
增加了時間限制,其實沒有外部信號,在等待時間超時后,線程也會恢復。
TERMINATED
TERMINATED
是線程的終止態,當線程執行完自己的任務,或在執行任務中發生了異常,線程都會進入TERMINATED
,表示線程已經到了生命周期的末尾。
下圖是關於線程間各狀態切換的過程及發生狀態切換的一些條件。
操作 | 操作前線程狀態 | 操作后線程狀態 | 是否出讓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();
}
}
}
詳細代碼可以GitHub