来源:https://blog.csdn.net/limenghua9112/article/details/106975105
为何要了解Java线程状态
线程是 JVM 执行任务的最小单元,理解线程的状态转换是理解后续多线程问题的基础。
Java线程状态转换图
Java线程有哪些状态?
在 JVM 运行中,线程一共有 NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED 六种状态,这些状态对应 Thread.State
枚举类中的状态。
推荐一个开源免费的 Spring Boot 实战项目:
https://github.com/javastacks/spring-boot-best-practice
Thread.State枚举源码:
为方便阅读,在此去掉了文档注释
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
在给定的时间点,线程只能处于这些状态中的一种状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
NEW,TERMINATED
这两个状态比较好理解,当创建一个线程后,还没有调用start()方法时,线程处在 NEW 状态,线程完成执行,退出后变为TERMINATED终止状态。
RUNNABLE
运行 Thread 的 start 方法后,线程进入 RUNNABLE 可运行状态
/**
* 程序目的:观察线程的各种状态
* created at 2020-06-26 19:09
* @author lerry
*/
class MyThread extends Thread {
@Override
public void run() {
System.out.printf("%s线程运行\n", Thread.currentThread().getName());
}
}
/**
* 分别观察创建线程后、start()后、和线程退出后的线程状态。
* 其中Thread.sleep(50);是为了等待线程执行完
*/
public class ThreadStateDemo {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.printf("创建线程后,线程的状态为:%s\n", myThread.getState());
myThread.start();
System.out.printf("调用start()方法后线程的状态为:%s\n", myThread.getState());
// 休眠50毫秒,等待MyThread线程执行完
Thread.sleep(50);
System.out.printf("再次打印线程的状态为:%s\n", myThread.getState());
}
}
输出结果:
创建线程后,线程的状态为:NEW
调用start()方法后线程的状态为:RUNNABLE
Thread-0线程运行
再次打印线程的状态为:TERMINATED
我们可以看到,输出结果符合预期。
- 在刚创建完线程后,状态为NEW
- 调用了start()方法后线程的状态变为:RUNNABLE。
- 然后,我们看到了run()方法的执行,这个执行,是在主线程main打印了调用start()方法后线程的状态为:RUNNABLE输出后执行的。
- 随后,我们让main线程休眠了50毫秒,等待MyThread线程退出
- 最后再打印MyThread线程的状态,为TERMINATED。
BLOCKED
如图左侧所示,在运行态中的线程进入 synchronized 同步块或者同步方法时,如果获取锁失败,则会进入到 BLOCKED 状态。当获取到锁后,会从 BLOCKED 状态恢复到就绪状态。
import lombok.extern.slf4j.Slf4j;
/**
* 程序目的:观察线程的BLOCKED状态
* created at 2020-06-26 19:09
* @author lerry
*/
@Slf4j
public class ThreadBlockedStateDemo {
public static void main(String[] args) {
Thread threadA = new Thread(() -> method01(), "A-Thread");
Thread threadB = new Thread(() -> method01(), "B-Thread");
threadA.start();
threadB.start();
log.info("线程A的状态为:{}", threadA.getState());
log.info("线程B的状态为:{}", threadB.getState());
}
/**
* 停顿10毫秒、模拟方法执行耗时
*/
public static synchronized void method01() {
log.info("[{}]:开始执行主线程的方法", Thread.currentThread().getName());
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
e.printStackTrace();
}
log.info("[{}]:主线程的方法执行完毕", Thread.currentThread().getName());
}
}
输出结果:
2020-06-26 20:32:15.404 [A-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [A-Thread]:开始执行主线程的方法
2020-06-26 20:32:15.404 [main ] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - 线程A的状态为:RUNNABLE
2020-06-26 20:32:15.407 [main ] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - 线程B的状态为:BLOCKED
2020-06-26 20:32:15.417 [A-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [A-Thread]:主线程的方法执行完毕
2020-06-26 20:32:15.418 [B-Thread] INFO com.hua.threadtest.state.ThreadBlockedStateDemo - [B-Thread]:开始执行主线程的方法
2020-06-26 20:32:15.430 [B-Thread] INFO com.hua.thread