線程thread的狀態(tài)有六種:
new、terminal、runnable、waiting、timed_waiting、block
它們的關(guān)系圖如下:

代碼測(cè)試:
/**
* 線程的狀態(tài),有六種:
* NEW 、新建
* RUNNABLE 、可運(yùn)行
* WAITING、等待
* TIMED_WAITING、限時(shí)等待
* BLOCKED、阻塞
* TERMINAL、終止
*
* @author Administrator
*/
public class ThreadState {
public static void main(String[] args) {
System.out.println("============================測(cè)試 NEW RUNNABLE TERMINAL TIMED_WAITING============================");
Sub a = new Sub("a");
SmallTool.printTimeAndThread("新建了一個(gè)線程a,但還沒(méi)start,狀態(tài):" + a.getState());//NEW
a.start();
SmallTool.printTimeAndThread("線程a已經(jīng)start,狀態(tài)是:" + a.getState());//RUNNABLE
SmallTool.printTimeAndThread("待線程" + Thread.currentThread() + "睡20ms,讓cpu給a線程,讓它睡眠5s");
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("查看a線程的狀態(tài):" + a.getState());//TIMED_WAITING
SmallTool.sleepMillis(5000);
SmallTool.printTimeAndThread("睡眠超過(guò)a的5s,查看a的狀態(tài):" + a.getState());//TERMINATED
//**************************************************************************************************
System.out.println("============================測(cè)試BLOCK============================");
Block b = new Block("b");
Block c = new Block("c");
b.start();
SmallTool.printTimeAndThread("b已經(jīng)啟動(dòng),c在20ms后啟動(dòng),讓b拿著synchronize鎖,睡眠5s");
SmallTool.sleepMillis(20);
c.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("待c啟動(dòng)成功之后,查看狀態(tài),b=" + b.getState() + " , c=" + c.getState());//b=TIMED_WAITING , c=BLOCKED
SmallTool.printTimeAndThread("c正在" + c.getState() + ",嘗試打斷它");
c.interrupt();
SmallTool.printTimeAndThread("在c被打斷后,查看打斷標(biāo)志:" + c.isInterrupted() + ",狀態(tài):" + c.getState());//isInterrupted=false, RUNNABLE
SmallTool.printTimeAndThread("c響應(yīng)中斷后不會(huì)再執(zhí)行run()方法D的睡5s,立馬往下執(zhí)行異常代碼");
//*******************************************************************************************************
SmallTool.sleepMillis(5 * 1000);
Wait d = new Wait("d");
SmallTool.sleepMillis(20);
System.out.println("============================測(cè)試WAIT 和 打斷它============================");
d.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("d已經(jīng)啟動(dòng)成功,內(nèi)執(zhí)行wait(),查看狀態(tài): " + d.getState()); //WAITING
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("過(guò)20ms打斷d,會(huì)拋出異常");
d.interrupt();
}
/**
* 運(yùn)行結(jié)果:
* ============================測(cè)試 NEW RUNNABLE TERMINAL TIMED_WAITING============================
1642177805719 | 1 | main | 新建了一個(gè)線程a,但還沒(méi)start,狀態(tài):NEW
1642177805721 | 1 | main | 線程a已經(jīng)start,狀態(tài)是:RUNNABLE
1642177805722 | 1 | main | 待線程Thread[main,5,main]睡20ms,讓cpu給a線程,讓它睡眠5s
1642177805733 | 11 | a | 在run()方法中睡眠5s...
1642177805762 | 1 | main | 查看a線程的狀態(tài):TIMED_WAITING
1642177810800 | 1 | main | 睡眠超過(guò)a的5s,查看a的狀態(tài):TERMINATED
============================測(cè)試BLOCK============================
1642177810867 | 1 | main | b已經(jīng)啟動(dòng),c在20ms后啟動(dòng),讓b拿著synchronize鎖,睡眠5s
1642177810925 | 1 | main | 待c啟動(dòng)成功之后,查看狀態(tài),b=TIMED_WAITING , c=BLOCKED
1642177810925 | 1 | main | c正在BLOCKED,嘗試打斷它
1642177810925 | 1 | main | 在c被打斷后,查看打斷標(biāo)志:true,狀態(tài):BLOCKED
1642177810925 | 1 | main | c響應(yīng)中斷后不會(huì)再執(zhí)行run()方法D的睡5s,立馬往下執(zhí)行異常代碼
1642177815886 | 12 | b | 完成業(yè)務(wù)了,狀態(tài)是:RUNNABLE
1642177815886 | 13 | c | 在-- block --被打斷并清除中斷標(biāo)志,標(biāo)志:false,狀態(tài)是:RUNNABLE
1642177815886 | 13 | c | 完成業(yè)務(wù)了,狀態(tài)是:RUNNABLE
============================測(cè)試WAIT 和 打斷它============================
1642177815998 | 1 | main | d已經(jīng)啟動(dòng)成功,內(nèi)執(zhí)行wait(),查看狀態(tài): WAITING
1642177816029 | 1 | main | 過(guò)20ms打斷d,會(huì)拋出異常
1642177816029 | 14 | d | 在-- wait --被打斷并清除中斷標(biāo)志,狀態(tài)是:RUNNABLE
*
*/
}
class Sub extends Thread {
public Sub(String name) {
super(name);
}
@Override
public void run() {
SmallTool.printTimeAndThread("在run()方法中睡眠5s...");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
SmallTool.printTimeAndThread("在-- sub --被打斷并清除中斷標(biāo)志,狀態(tài)是:" + Thread.currentThread().getState());
}
}
}
class Block extends Thread {
public Block(String name) {
super(name);
}
@Override
public void run() {
synchronized (Block.class) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
SmallTool.printTimeAndThread("在-- block --被打斷并清除中斷標(biāo)志,標(biāo)志:"
+ Thread.currentThread().isInterrupted() + ",狀態(tài)是:" + Thread.currentThread().getState());
} finally {
SmallTool.printTimeAndThread("完成業(yè)務(wù)了,狀態(tài)是:" + Thread.currentThread().getState());
}
}
}
}
class Wait extends Thread {
public Wait(String name) {
super(name);
}
@Override
public void run() {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
SmallTool.printTimeAndThread("在-- wait --被打斷并清除中斷標(biāo)志,狀態(tài)是:" + Thread.currentThread().getState());//WAITING
}
}
}
}
關(guān)于LockSupport的park之后的狀態(tài)
LockSupport的park被調(diào)用之后,線程狀態(tài)是WAITING,可以使用lockSupport的unpark或者使用該線程的interrupt方法來(lái)打斷,它倆都可以使程序繼續(xù)運(yùn)行。
測(cè)試代碼:
/**
* 測(cè)試lockSupport的狀態(tài)、使用unpark和interrupt之后的狀態(tài)
*
* 可以知道lockSupport的park之后,線程是處于waiting狀態(tài)的
*
* @author Administrator
*/
public class LockSupportState {
public static void main(String[] args) {
System.out.println("============================測(cè)試LockSupport是WAITING,以及unPark============================");
LockSupportPark e = new LockSupportPark("e");
e.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("讓e被park住,查看狀態(tài),e:" + e.getState());
LockSupport.unpark(e);
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("之后main線程使用unpark喚醒它,查看狀態(tài),e:" + e.getState());
SmallTool.sleepMillis(20);
System.out.println("============================測(cè)試LockSupport是WAITING,以及打斷============================");
LockSupportPark f = new LockSupportPark("f");
f.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("讓f被park住,查看狀態(tài),f:" + f.getState());
f.interrupt();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("之后main線程使用interrupt打斷它,查看狀態(tài),f:" + f.getState());
}
/**
* 運(yùn)行結(jié)果:
============================測(cè)試LockSupport是WAITING,以及unPark============================
1642177729984 | 11 | e | e線程被park之前
1642177730013 | 1 | main | 讓e被park住,查看狀態(tài),e:WAITING
1642177730013 | 11 | e | e線程被park之后
1642177730045 | 1 | main | 之后main線程使用unpark喚醒它,查看狀態(tài),e:TERMINATED
============================測(cè)試LockSupport是WAITING,以及打斷============================
1642177730077 | 12 | f | f線程被park之前
1642177730109 | 1 | main | 讓f被park住,查看狀態(tài),f:WAITING
1642177730109 | 12 | f | f線程被park之后
1642177730141 | 1 | main | 之后main線程使用interrupt打斷它,查看狀態(tài),f:TERMINATED
*/
}
class LockSupportPark extends Thread {
public LockSupportPark(String name) {
super(name);
}
@Override
public void run() {
SmallTool.printTimeAndThread(currentThread().getName() + "線程被park之前");
LockSupport.park(this);
SmallTool.printTimeAndThread(currentThread().getName() + "線程被park之后");
}
}
結(jié)論
對(duì)比一開(kāi)始的圖片,以上的測(cè)試結(jié)果基本都是符合的,進(jìn)入BLOCKED的只有synchronize的,其余變成WAITING的,都是lockSupport、wait、join、sleep之類的。
而且,通過(guò)以上實(shí)驗(yàn),NEW和TERMINATED對(duì)于中斷操作幾乎是屏蔽的,RUNNABLE和BLOCKED類似,對(duì)于中斷操作只是設(shè)置中斷標(biāo)志位并沒(méi)有強(qiáng)制終止線程,對(duì)于線程的終止權(quán)利依然在程序手中。WAITING/TIMED_WAITING狀態(tài)下的線程對(duì)于中斷操作是敏感的,他們會(huì)拋出異常并清空中斷標(biāo)志位。