• Java 线程的几种状态


    一. 线程的几种状态

    1.观察线程的所有状态

    线程的状态是一个枚举类型 Thread.state

    1. public static void main(String[] args) {
    2. for (Thread.State state : Thread.State.values()) {
    3. System.out.println(state);
    4. }
    5. }

    下面我详细解释一下这几种状态的含义:

    2.线程状态的含义

    • NEW : Thread 对象被创建出来, 但是内核的PCB还没创建(还没真正的创建线程)
    • TERMINATED : 内核的PCB销毁了, 但是Thread对象还在
    • RUNNABLE : 就绪状态. (正在CPU上运行 + 在就绪队列中排队)
    • TIMED_WAITING : 按照一定的时间, 进行阻塞, sleep.
    • WAITING : 特殊的阻塞状态, 调用wait.
    • BLOCKED : 等待锁的时候进入的阻塞状态.

    3.线程状态和状态转移

     从上图来看, 最开始是一个 NEW 状态, 然后进入 RUNNABLE 状态, 也就是线程开始运行了, 再然后运行完了就进入 TERMINATED 状态, 这是主干道, 线程从开始到结束的状态, 然后再 RUNNABLE 过程中可能会产生其他状态, 就是 TIMED_WAITING 和 BLOCKED 和 WAITING, RUNNABLE 可以在这三个状态之间转换, 怎样进入 WAITING 状态呢, 也就是 wait方法和join()不带参数的版本, 要是进入 TIMED_WAITING 状态呢, 就是sleep和join(time)带时间的版本, 而进入 BLOCKED 呢就是加锁 synchronized ,这是整体的状态转换.

    下面我们通过代码看一下状态的变化:

    1. public static void main(String[] args) {
    2. Thread thread = new Thread( () -> {
    3. for (int i = 0; i < 1000_000; i++) {
    4. // 在这个循环里什么也不干
    5. }
    6. });
    7. // 此时 thread 得到的就是 NEW
    8. System.out.println(thread.getState());
    9. thread.start();
    10. try {
    11. thread.join();
    12. } catch (InterruptedException e) {
    13. e.printStackTrace();
    14. }
    15. // thread 结束之后, 得到的状态就是 TERMINATED
    16. System.out.println(thread.getState());
    17. }

     而在 start 和 join() 之间获取状态的话, 就是 RUNNABLE.

     

     而我们要是在运行中的时候用上 sleep 和 join(time) 带时间的版本, 得到的状态就是 TIME_WAITING.

    1. public static void main(String[] args) throws InterruptedException {
    2. Thread thread = new Thread( () -> {
    3. // for (int i = 0; i < 100_000_000; i++) {
    4. // // 在这个循环里什么也不干
    5. // }
    6. try {
    7. Thread.sleep(2000);
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. });
    12. // 此时 thread 得到的就是 NEW
    13. System.out.println(thread.getState());
    14. thread.start();
    15. Thread.sleep(50);
    16. //thread.join(10000);
    17. // thread 正在运行中, 此时得到的状态就是 RUNNABLE
    18. System.out.println(thread.getState());
    19. try {
    20. thread.join();
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. // thread 结束之后, 得到的状态就是 TERMINATED
    25. System.out.println(thread.getState());
    26. }

     

     运行的时候, 遇到 sleep , 得到的状态就是 TIMED_WAITING, 没有的话就是 RUNNABLE 状态.

    下面来看一下 BLOCKED 和 RUNNABLE 的转换:

    处于 BLOCKED 状态的线程是因为在等待锁的释放。假如有两个线程 t1 和 t2,t1 线程提前获得了锁并且暂未释放锁,此时 t2 就处于 BLOCKED 状态。

    1. public static void main(String[] args) {
    2. Thread t1 = new Thread(new Runnable() {
    3. @Override
    4. public void run() {
    5. test();
    6. }
    7. }, "t1");
    8. Thread t2 = new Thread(new Runnable() {
    9. @Override
    10. public void run() {
    11. test();
    12. }
    13. }, "t2");
    14. t1.start();
    15. t2.start();
    16. System.out.println(t1.getName() + ":" + t1.getState());
    17. System.out.println(t2.getName() + ":" + t2.getState());
    18. }
    19. // 争夺锁
    20. private static synchronized void test() {
    21. try {
    22. Thread.sleep(2000L);
    23. } catch (InterruptedException e) {
    24. e.printStackTrace();
    25. }
    26. }

     从打印结果我们就可以看出来, t1 线程因为先于 t2 线程获得锁并且还在未释放的状态下, t1 线程处于 RUNNABLE 状态下, t2 线程处于 BLOCKED 状态下. 

    而当我们让 main 线程休眠1000毫秒的话, 此时线程状态转换就是:

     

    1.  t1 的状态转换过程就是从开始启动线程的 RUNNABLE , 到 sleep 休眠的 TIMED_WAITING , 然后 sleep() 的时间一到, 就是 RUNNABLE, 然后和 t2 线程进行锁竞争,而由于没抢到锁就是到 BLOCKED(未加锁), 再到后面的  TERMINATED
    2. t2 的状态转换过程是, 从开始启动线程的 RUNNABLE ,  到 BLOCKED(未抢到锁) ,然后也是 TERMINATED.

  • 相关阅读:
    常用的数据库连接池、配置参数及相应的调优方法
    一些工具/网站自用总结
    Flink中的时间和窗口操作
    Mac安装虚拟机和CentOS
    Android RecyclerView 之 吸顶效果
    MATLAB2016笔记(六):数据可视化
    305页18万字智慧三甲医院弱电系统设计方案完整版
    第六篇:常用Linux命令
    [论文阅读] 颜色迁移-颜色空间的选择
    全智V5+AXP233电源管理芯片调试
  • 原文地址:https://blog.csdn.net/qq_52592775/article/details/127741964