線程用了多年勉耀,一直是處于只會用的狀態(tài)指煎,最近想詳細的研究一下多線程,在這里做一下記錄便斥。在Thread中一共有6種狀態(tài)至壤。
- NEW : 創(chuàng)建了Thread對象,但尚未啟動的線程的線程狀態(tài).
- RUNNABLE : 調(diào)用start()方法后的可運行狀態(tài)枢纠,這個狀態(tài)可以切換到除了NEW之外的任何其它狀態(tài)像街。
- BLOCKED :線程阻塞狀態(tài)。等待監(jiān)視器的鎖晋渺,拿到鎖后切換回RUNNABLE繼續(xù)執(zhí)行镰绎。
- WAITING : 線程等待狀態(tài)(no timeout). RUNNABLE狀態(tài)中的線程在掉用Object#wait()、join()或者LockSupport#park()后會進入這個狀態(tài)木西。
- TIMED_WAITING : 線程等待狀態(tài)(timeout). RUNNABLE狀態(tài)中的線程在掉用#sleep畴栖、Object#wait(long)、join(long)八千、LockSupport#parkNanos吗讶、LockSupport#parkUntil后會進入到這個狀態(tài)。
- TERMINATED : 線程運行完畢的線程終止狀態(tài)恋捆。RUNNABLE 執(zhí)行結(jié)束照皆。
關(guān)系圖如下圖所示
示例代碼如下:
/**
* 示例2 - 多線程運行狀態(tài)切換示例 <br/>
*/
public class Demo2 {
public static Thread thread1;
public static Demo2 obj;
public static void main(String[] args) throws Exception {
// 第一種狀態(tài)切換 - 新建 -> 運行 -> 終止
System.out.println("#######第一種狀態(tài)切換 - 新建 -> 運行 -> 終止################################");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread1當前狀態(tài):" + Thread.currentThread().getState().toString());
System.out.println("thread1 執(zhí)行了");
}
});
System.out.println("沒調(diào)用start方法,thread1當前狀態(tài):" + thread1.getState().toString());
thread1.start();
Thread.sleep(2000L); // 等待thread1執(zhí)行結(jié)束沸停,再看狀態(tài)
System.out.println("等待兩秒膜毁,再看thread1當前狀態(tài):" + thread1.getState().toString());
// thread1.start(); TODO 注意,線程終止之后愤钾,再進行調(diào)用爽茴,會拋出IllegalThreadStateException異常
System.out.println();
System.out.println("############第二種:新建 -> 運行 -> 等待 -> 運行 -> 終止(sleep方式)###########################");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {// 將線程2移動到等待狀態(tài),1500后自動喚醒
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2當前狀態(tài):" + Thread.currentThread().getState().toString());
System.out.println("thread2 執(zhí)行了");
}
});
System.out.println("沒調(diào)用start方法绰垂,thread2當前狀態(tài):" + thread2.getState().toString());
thread2.start();
System.out.println("調(diào)用start方法室奏,thread2當前狀態(tài):" + thread2.getState().toString());
Thread.sleep(200L); // 等待200毫秒,再看狀態(tài)
System.out.println("等待200毫秒劲装,再看thread2當前狀態(tài):" + thread2.getState().toString());
Thread.sleep(3000L); // 再等待3秒胧沫,讓thread2執(zhí)行完畢昌简,再看狀態(tài)
System.out.println("等待3秒,再看thread2當前狀態(tài):" + thread2.getState().toString());
System.out.println();
System.out.println("############第三種:新建 -> 運行 -> 阻塞 -> 運行 -> 終止###########################");
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (Demo2.class) {
System.out.println("thread3當前狀態(tài):" + Thread.currentThread().getState().toString());
System.out.println("thread3 執(zhí)行了");
}
}
});
synchronized (Demo2.class) {
System.out.println("沒調(diào)用start方法绒怨,thread3當前狀態(tài):" + thread3.getState().toString());
thread3.start();
System.out.println("調(diào)用start方法纯赎,thread3當前狀態(tài):" + thread3.getState().toString());
Thread.sleep(200L); // 等待200毫秒,再看狀態(tài)
System.out.println("等待200毫秒南蹂,再看thread3當前狀態(tài):" + thread3.getState().toString());
}
Thread.sleep(3000L); // 再等待3秒犬金,讓thread3執(zhí)行完畢,再看狀態(tài)
System.out.println("等待3秒六剥,讓thread3搶到鎖晚顷,再看thread3當前狀態(tài):" + thread3.getState().toString());
}
}
運行結(jié)果:
#######第一種狀態(tài)切換 - 新建 -> 運行 -> 終止################################
沒調(diào)用start方法,thread1當前狀態(tài):NEW
thread1當前狀態(tài):RUNNABLE
thread1 執(zhí)行了
等待兩秒疗疟,再看thread1當前狀態(tài):TERMINATED
############第二種:新建 -> 運行 -> 等待 -> 運行 -> 終止(sleep方式)###########################
沒調(diào)用start方法该默,thread2當前狀態(tài):NEW
調(diào)用start方法,thread2當前狀態(tài):RUNNABLE
等待200毫秒策彤,再看thread2當前狀態(tài):TIMED_WAITING
thread2當前狀態(tài):RUNNABLE
thread2 執(zhí)行了
等待3秒栓袖,再看thread2當前狀態(tài):TERMINATED
############第三種:新建 -> 運行 -> 阻塞 -> 運行 -> 終止###########################
沒調(diào)用start方法,thread3當前狀態(tài):NEW
調(diào)用start方法店诗,thread3當前狀態(tài):RUNNABLE
等待200毫秒裹刮,再看thread3當前狀態(tài):BLOCKED
thread3當前狀態(tài):RUNNABLE
thread3 執(zhí)行了
等待3秒,讓thread3搶到鎖庞瘸,再看thread3當前狀態(tài):TERMINATED
Process finished with exit code 0