Java线程状态
1.1 Java线程状态概述
我们可以通过Java内部提供的枚举类型Thread.State
,查看所有的Java线程状态
public class ThreadDemo16 {
public static void main(String[] args) {
for (Thread.State state : Thread.State.values()) {
System.out.println(state);
}
}
}
打印结果如下图所示:
NEW
:表示线程处于新建状态,但是仍未开始执行任务(调用start方法之前)RUNNABLE
:表示线程处于已就绪状态,此时线程正处于CPU上调度或者可以随时被CPU调度BLOCKED
:表示当前线程由于锁竞争处于阻塞等待状态WAITING
:表示当前线程处于阻塞等待状态TIMED_WATING
:表示当前线程处于带有时限的阻塞等待状态(超时等待)TERMINATED
:表示当前线程任务完成,处于终止状态(run方法执行完毕)
1.2 Java线程状态图
上图描述的就是Java中的线程状态模型,可以概括线程的生命周期。下面我们举一个生动形象的生活案例来解释每个状态所表示的含义:
考虑这样一个场景:中午到了饭点了,你和大伙一起去食堂吃饭。这时每一个窗口都只有一位食堂阿姨为同学们打饭,你到达你最喜欢的烤肉饭窗口发现前方已经有很多同学都在排队了,礼貌懂事的你自觉的到队列尾部进行排队。此时就是一个多线程模型,下面将解释此背景中各种状况及对应的线程状态。
NEW
:你此时正处于前往食堂的路上,你知道自己要去吃饭,但是并不能立马吃上(已经分配任务,但是无法被CPU调度)RUNNABLE
:此时你羡慕的望着队头正在点菜的同学,这个线程可以或是正在被CPU调度(处于就绪状态)TIME_WAITED | WAITED
:此时饭菜卖完了,后勤正在进行补给当中,同学们需要进行等待(阻塞等待状态)BLOCKED
:排队过程中,你看到有两位同学因为竞争一双筷子起了冲突,此时筷子可以看作锁对象,持有筷子的一方就是持有锁对象,另一方由于锁冲突需要阻塞等待(锁冲突导致的阻塞等待)TERMINATED
:最后的最后,你终于吃上你心爱的烤肉饭了,此时你吃饭的任务已经完成(处于终止状态)
1.3 观察线程状态的切换
1.3.1 观察NEW、RUNNABLE、TERMINATED状态切换
-
使用
getState
方法获取线程的运行状态public class ThreadDemo18 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { System.out.println("当前t线程状态:" + Thread.currentThread().getState()); }); System.out.println("当前t线程状态:" + t.getState()); t.start(); t.join(); System.out.println("当前t线程状态:" + t.getState()); } }
1.3.2 观察WAITING、TIMED_WAITING、BLOCKED状态切换
-
通过jconsole工具获取线程状态
public class ThreadDemo19 { private static Object obj = new Object(); public static void main(String[] args) { Thread t1 = new Thread(() -> { synchronized (obj) { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t1.start(); Thread t2 = new Thread(() -> { synchronized (obj) { System.out.println("我好想要执行..."); } }); t2.start(); } }
通过jconsole工具可以查看线程此时的状态:Thread-0处于超时等待状态,Thread-1处于BLOCKED状态
这是因为线程Thread-0先被执行并且进入
synchronized
代码块中,获得锁对象并调用Thread.sleep(long millis)
方法处于线程休眠超时等待状态,线程Thread-1由于争夺同一个锁对象,但是此时锁对象被Thread-0获取,处于BLOCKED
状态
如果将代码稍加修改,让Thread-0中执行
sleep(long millis)
方法改成wait()
此时线程Thread-0的状态就是WAITING
状态:此时Thread-0线程执行
wait()
方法后做了以下三件事:①、释放当前锁 ②、处于阻塞等待状态 ③、直到别的线程唤醒则继续执行。但是没有别的线程唤醒该线程于是一直处于WAITING
状态。 -
小节:
- BLOCKED 表示等待获取锁, WAITING 和 TIMED_WAITING 表示等待其他线程发来通知.
- TIMED_WAITING 线程在等待唤醒,但设置了时限; WAITING 线程在无限等待唤醒