❣️关注专栏: JavaEE
对当前线程调度的情况我们用状态来描述。线程调度的最基本的单位,那么状态更应该是线程的属性。线程的状态是一个枚举类型 Thread.State,里边包含了6个状态。
public class ThreadState {
public static void main(String[] args) {
for (Thread.State state : Thread.State.values()) {
System.out.println(state);
}
}
}
在Java中我们对线程的状态进行了细化,主要分为了6个状态。状态如下:
其中 3、4、5 都是阻塞,表示线程PCB正在阻塞队列中。
这几个状态都是不同原因的阻塞。
在这里解释一个疑惑:为什么PCB都释放了,线程的对象还在呢?此时线程存在的意义是什么?
直白来说,此时线程的存在是没有意义的,但是Java里做不到和内核的线程销毁同步释放对象。一旦内核里的线程PCB消亡了,此时代码中的线程的对象就没用了,之所对象还存在着,是因为 Java 中对象的生命周期有它自己的规则,这个生命周期和内核里的线程并非完全一致,内核的线程释放的时候,无法保证Java代码中的线程的对象也立即释放,在这个时候,就需要通过特定的状态把线程的对象标识为“无效”。
PCB没了,但是对象还在,我们还可以调用对象的方法属性,只是没法通过多线程来做一些操作了。
刚开始我们就先来看这4个状态 NEW 、 RUNNABLE 、TIMED_WAITING、 TERMINATED 的转换,后续我们再看其他的状态转移切换。
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
// 1.这个循环啥都不干,也不 sleep ---> 如果什么都不干,那么在下边 t 执行中的状态:为 RUNNABLE
}
});
// 启动之前,获取 t 的状态,就是 new 状态
System.out.println("start 之前:"+t.getState());
t.start();
// 线程执行完毕之后,就是 TERMINATED 状态
System.out.println(" t 结束之后:" + t.getState());
}
代码执行结果:
之所以能够看到 RUNNABLE,是因为当前线程 run 里边没有写 sleep 之类的方法
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
/* 2.加入 sleep 方法 ---> 此处在后续打印状态中,具体看到的是 RUNNABLE 还是 TIMED_WAITING
就不一定了取决于当前 t 线程运行到了哪个环节
*/
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 启动之前,获取 t 的状态,就是 new 状态
System.out.println("start 之前:"+t.getState());
t.start();
/* 通过循环获取,就能看到交替状态了,当前获取的状态是什么,完全取决于系统的调度操作
获取状态的这一瞬间,到底 t 线程是在什么样的状态(正在执行,还是正在 sleep)
*/
for (int i = 0; i < 1000; i++) {
System.out.println(" t 执行中的状态:" + t.getState());
}
t.join(); // 此处的 join 就是让当前的 main 线程来等待 t 线程执行结束(等待 t 的 run 执行完)
// 线程执行完毕之后,就是 TERMINATED 状态
System.out.println(" t 结束之后:" + t.getState());
}
运行结果较长,小编就不截图了,还请读者自行运行查看哦!!!
之前我们学过的 isAlive() 方法,可以认为是处于不是 NEW 和 TERMINATED 的状态都是活着的。