线程thread的状态有六种:
new、terminal、runnable、waiting、timed_waiting、block
它们的关系图如下:
代码测试:
/**
* 线程的状态,有六种:
* NEW 、新建
* RUNNABLE 、可运行
* WAITING、等待
* TIMED_WAITING、限时等待
* BLOCKED、阻塞
* TERMINAL、终止
*
* @author Administrator
*/
public class ThreadState {
public static void main(String[] args) {
System.out.println("============================测试 NEW RUNNABLE TERMINAL TIMED_WAITING============================");
Sub a = new Sub("a");
SmallTool.printTimeAndThread("新建了一个线程a,但还没start,状态:" + a.getState());//NEW
a.start();
SmallTool.printTimeAndThread("线程a已经start,状态是:" + a.getState());//RUNNABLE
SmallTool.printTimeAndThread("待线程" + Thread.currentThread() + "睡20ms,让cpu给a线程,让它睡眠5s");
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("查看a线程的状态:" + a.getState());//TIMED_WAITING
SmallTool.sleepMillis(5000);
SmallTool.printTimeAndThread("睡眠超过a的5s,查看a的状态:" + a.getState());//TERMINATED
//**************************************************************************************************
System.out.println("============================测试BLOCK============================");
Block b = new Block("b");
Block c = new Block("c");
b.start();
SmallTool.printTimeAndThread("b已经启动,c在20ms后启动,让b拿着synchronize锁,睡眠5s");
SmallTool.sleepMillis(20);
c.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("待c启动成功之后,查看状态,b=" + b.getState() + " , c=" + c.getState());//b=TIMED_WAITING , c=BLOCKED
SmallTool.printTimeAndThread("c正在" + c.getState() + ",尝试打断它");
c.interrupt();
SmallTool.printTimeAndThread("在c被打断后,查看打断标志:" + c.isInterrupted() + ",状态:" + c.getState());//isInterrupted=false, RUNNABLE
SmallTool.printTimeAndThread("c响应中断后不会再执行run()方法D的睡5s,立马往下执行异常代码");
//*******************************************************************************************************
SmallTool.sleepMillis(5 * 1000);
Wait d = new Wait("d");
SmallTool.sleepMillis(20);
System.out.println("============================测试WAIT 和 打断它============================");
d.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("d已经启动成功,内执行wait(),查看状态: " + d.getState()); //WAITING
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("过20ms打断d,会抛出异常");
d.interrupt();
}
/**
* 运行结果:
* ============================测试 NEW RUNNABLE TERMINAL TIMED_WAITING============================
1642177805719 | 1 | main | 新建了一个线程a,但还没start,状态:NEW
1642177805721 | 1 | main | 线程a已经start,状态是:RUNNABLE
1642177805722 | 1 | main | 待线程Thread[main,5,main]睡20ms,让cpu给a线程,让它睡眠5s
1642177805733 | 11 | a | 在run()方法中睡眠5s...
1642177805762 | 1 | main | 查看a线程的状态:TIMED_WAITING
1642177810800 | 1 | main | 睡眠超过a的5s,查看a的状态:TERMINATED
============================测试BLOCK============================
1642177810867 | 1 | main | b已经启动,c在20ms后启动,让b拿着synchronize锁,睡眠5s
1642177810925 | 1 | main | 待c启动成功之后,查看状态,b=TIMED_WAITING , c=BLOCKED
1642177810925 | 1 | main | c正在BLOCKED,尝试打断它
1642177810925 | 1 | main | 在c被打断后,查看打断标志:true,状态:BLOCKED
1642177810925 | 1 | main | c响应中断后不会再执行run()方法D的睡5s,立马往下执行异常代码
1642177815886 | 12 | b | 完成业务了,状态是:RUNNABLE
1642177815886 | 13 | c | 在-- block --被打断并清除中断标志,标志:false,状态是:RUNNABLE
1642177815886 | 13 | c | 完成业务了,状态是:RUNNABLE
============================测试WAIT 和 打断它============================
1642177815998 | 1 | main | d已经启动成功,内执行wait(),查看状态: WAITING
1642177816029 | 1 | main | 过20ms打断d,会抛出异常
1642177816029 | 14 | d | 在-- wait --被打断并清除中断标志,状态是: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 --被打断并清除中断标志,状态是:" + 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 --被打断并清除中断标志,标志:"
+ Thread.currentThread().isInterrupted() + ",状态是:" + Thread.currentThread().getState());
} finally {
SmallTool.printTimeAndThread("完成业务了,状态是:" + 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 --被打断并清除中断标志,状态是:" + Thread.currentThread().getState());//WAITING
}
}
}
}
关于LockSupport的park之后的状态
LockSupport的park被调用之后,线程状态是WAITING,可以使用lockSupport的unpark或者使用该线程的interrupt方法来打断,它俩都可以使程序继续运行。
测试代码:
/**
* 测试lockSupport的状态、使用unpark和interrupt之后的状态
*
* 可以知道lockSupport的park之后,线程是处于waiting状态的
*
* @author Administrator
*/
public class LockSupportState {
public static void main(String[] args) {
System.out.println("============================测试LockSupport是WAITING,以及unPark============================");
LockSupportPark e = new LockSupportPark("e");
e.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("让e被park住,查看状态,e:" + e.getState());
LockSupport.unpark(e);
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("之后main线程使用unpark唤醒它,查看状态,e:" + e.getState());
SmallTool.sleepMillis(20);
System.out.println("============================测试LockSupport是WAITING,以及打断============================");
LockSupportPark f = new LockSupportPark("f");
f.start();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("让f被park住,查看状态,f:" + f.getState());
f.interrupt();
SmallTool.sleepMillis(20);
SmallTool.printTimeAndThread("之后main线程使用interrupt打断它,查看状态,f:" + f.getState());
}
/**
* 运行结果:
============================测试LockSupport是WAITING,以及unPark============================
1642177729984 | 11 | e | e线程被park之前
1642177730013 | 1 | main | 让e被park住,查看状态,e:WAITING
1642177730013 | 11 | e | e线程被park之后
1642177730045 | 1 | main | 之后main线程使用unpark唤醒它,查看状态,e:TERMINATED
============================测试LockSupport是WAITING,以及打断============================
1642177730077 | 12 | f | f线程被park之前
1642177730109 | 1 | main | 让f被park住,查看状态,f:WAITING
1642177730109 | 12 | f | f线程被park之后
1642177730141 | 1 | main | 之后main线程使用interrupt打断它,查看状态,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之后");
}
}
结论
对比一开始的图片,以上的测试结果基本都是符合的,进入BLOCKED的只有synchronize的,其余变成WAITING的,都是lockSupport、wait、join、sleep之类的。
而且,通过以上实验,NEW和TERMINATED对于中断操作几乎是屏蔽的,RUNNABLE和BLOCKED类似,对于中断操作只是设置中断标志位并没有强制终止线程,对于线程的终止权利依然在程序手中。WAITING/TIMED_WAITING状态下的线程对于中断操作是敏感的,他们会抛出异常并清空中断标志位。
网友评论