线程状态
关于Java中的线程状态,去网上找相关资料发现说法并不相同。虽然不同语言中的线程中的线程状态大同小异,但是在Java中存在的线程状态只有六种。这六种线程状态在「Thread」类中有说明,在Thread类中有一个「State」枚举,该枚举中定义了Java中线程的状态。
New
如果一个线程刚被创建出来还未启动,那么该线程就处于该状态。
Thread t1 = new Thread();
log.info("t1 = {}",t1.getState());
RUNNABLE
可运行线程的线程状态。处在可运行状态的线程正在Java虚拟机中执行,但是它可能正在等待来自操作系统的其他资源,主要是指CPU资源。
Thread t2 = new Thread(() -> {
while (true){}
});
t2.start();
log.info("t2 = {}",t2.getState());
BLOCKED
受阻塞并等待某个监视锁的线程就处于该状态。处于受阻塞状态的某一线程正在等待监视器锁,以便进入一个同步的代码块或者方法。
Object o = new Object();
Thread t3 = new Thread(() ->{
synchronized (o){
while (true){
}
}
});
Thread t4 = new Thread(() ->{
synchronized (o){
while (true){
}
}
});
t3.start();
t4.start();
//增加1s延时,如果不添加可能线程还没启动看不到处于BLOCKED的线程状态
Thread.sleep(1000);
log.info("t3 = {},t4 = {}",t3.getState(),t4.getState());
例如上面状态的代码,线程t3和t4都在争夺实例对象「o」的监视锁,但是只有一个线程能获取成功。所以最后的结果是一个处于RUNNABLE状态,另一个则处于BLOCKED状态。
WAITING
某一等待线程的线程状态。简单的说就是处于等待状态的线程正在等待另一线程,以执行特定操作。通常在下面情况下线程会进入等待状态:
-
不带超时值的Object.wait -
不带超时值的Thread.join -
LockSupport.park
Object syncObject = new Object();
Thread t5 = new Thread(()->{
synchronized (syncObject){
try {
syncObject.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t5.start();
Thread.sleep(1000);
Thread t6 = new Thread(()->{
synchronized (syncObject){
try {
log.info("t5 = {},t6 = {}",t5.getState(),Thread.currentThread().getState());
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
syncObject.notify();
}
});
t6.start();
上面代码中有两个线程t5和t6,还有一个同步对象syncObject。t5先获取到同步对象进入同步代码块,接着代码t5线程调用同步对象的wait方法,释放掉同步对象t6获取到锁。这时打印出t5和t6线程的状态分别为「WAITING」 和 「RUNNABLE」。
Thread t7 = new Thread(() -> {
Thread t8 = new Thread(() ->{
while (true){}
});
t8.start();
try {
log.info("t8调用join");
t8.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t7.start();
Thread.sleep(1500);
log.info("t7 = {}",t7.getState());
上面的代码,线程t7内创建线程t8然后启动线程t8,t8启动后调用t8.join,这样线程t7就不能直接退出必须等待线程t8执行之后才会退出,而这个时候的线程状态就是「WAITING」。
Thread t9 = new Thread(() ->{
log.info("LockSupport 前:{}",Thread.currentThread().getState());
LockSupport.park();
log.info("LockSupport执行完成后");
});
t9.start();
Thread.sleep(1000);
log.info("t9 = {}",t9.getState());
LockSupport.unpark(t9);
log.info("调用unpark t9");
线程t9启动后内部调用 「LockSupport.park()」 方法后进入waiting状态。然后通过在主线程中打印出线程t9的状态,最后调用「LockSupport.unpark(t9)」。
TIMED_WAITING
具有指定等待时间的某一等待线程的线程状态。与WAITING类似,不同的在于WAITING没有指定时间。在触发方法上多了Thread.sleep方法。
TERMINATED
已终止线程的线程状态。如果线程处于该状态说明线程已执行完成。
Thread t10 = new Thread(() -> log.info("t10执行完毕!"));
t10.start();
t10.join();
log.info("t10 = {}",t10.getState());
小结
Java中的线程只会处于上述的六种状态,其他状态比较好区分,不太好区分的是WAITING和BLOCKED状态。这两个状态的本质区别在于:
-
BLOCKED是线程因为缺少锁而导致进入的阻塞,它的阻塞是因为缺少资源。 -
而WAITING不是因为缺少资源,而是它需要等待另外一个线程的特定操作。通常来说需要等待另一线程的notify或者notifyAll操作。

借用网上的一张图,该图完整的展示了Java线程的各种状态以及各种状态的转换规则。详细了解线程的状态,这个对于dump线程线程很重要,也有利于多线程其他知识的学习。
原文始发于微信公众号(一只菜鸟程序员):Java中的线程状态
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73058.html