• Java线程状态


    1主线程与守护线程

    默认情况下,Java 进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守 护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

    log.debug("开始运行...");
    Thread t1 = new Thread(() -> {
             while(true) {
                    boolean interrupted = Thread.currentThread().isInterrupted();
                    if(interrupted) {
                        log.debug("被打断了, 退出循环");
                        break;
                    }
             }
    
    }, "daemon");
    t1.start();
    sleep(1);
    log.debug("运行结束...");
    /*
    运行结果: 主线程运行完, 结束,流程不会结束,t1线程还在运行
    08:26:38.123 [main] c.TestDaemon - 开始运行... 
    08:26:39.215 [main] c.TestDaemon - 运行结束... 
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    非守护线程结束,守护线程会立即运行结束

    log.debug("开始运行...");
    Thread t1 = new Thread(() -> {
     log.debug("开始运行...");
     sleep(2);
     log.debug("运行结束...");
    }, "daemon");
    // 设置该线程为守护线程
    t1.setDaemon(true);
    t1.start();
    sleep(1);
    log.debug("运行结束...");
    /*
    运行结果:
    08:26:38.123 [main] c.TestDaemon - 开始运行... 
    08:26:38.213 [daemon] c.TestDaemon - 开始运行... 
    08:26:39.215 [main] c.TestDaemon - 运行结束... 
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2 五种状态(操作系统)

    以操作系统层面:

    在这里插入图片描述

    • 初始状态 仅是在语言层面创建了线程对象,还未与操作系统线程关联
    • 可运行状态 (就绪状态)指该线程已经被创建(与操作系统线程关联),可以由 CPU 调度执行
    • 运行状态 指获取了 CPU 时间片运行中的状态
      • 当 CPU 时间片用完,会从【运行状态】转换至【可运行状态】,会导致线程的上下文切换
    • 阻塞状态
      • 如果调用了阻塞 API,如 BIO 读写文件,这时该线程实际不会用到 CPU,会导致线程上下文切换,进入 【阻塞状态】
      • 等 BIO 操作完毕,会由操作系统唤醒阻塞的线程,转换至【可运行状态】
      • 与【可运行状态】的区别是,对【阻塞状态】的线程来说只要它们一直不唤醒,调度器就一直不会考虑 调度它们
    • 终止状态 表示线程已经执行完毕,生命周期已经结束,不会再转换为其它状态

    3 六种状态(Java的API)

    根据 Thread.State 枚举,分为六种状态:

    在这里插入图片描述

    • NEW 线程刚被创建,但是还没有调用 start() 方法

    • RUNNABLE 当调用了 start() 方法之后,注意,Java API 层面的 RUNNABLE 状态涵盖了 操作系统 层面的 【可运行状态】、【运行状态】和【阻塞状态】(由于 BIO 导致的线程阻塞,在 Java 里无法区分,仍然认为 是可运行)

    • BLOCKED , WAITING , TIMED_WAITING 都是 Java API 层面对【阻塞状态】的细分

    • TERMINATED 当线程代码运行结束

    线程状态案例

    @Slf4j(topic = "c.TestState")
    public class TestState {
        public static void main(String[] args) throws IOException {
            Thread t1 = new Thread("t1") {
                @Override
                public void run() {
                    log.debug("running...");
                }
            };
    
            // runnable
            Thread t2 = new Thread("t2") {
                @Override
                public void run() {
                    while(true) { 
    
                    }
                }
            };
            t2.start();
    
            Thread t3 = new Thread("t3") {
                @Override
                public void run() {
                    log.debug("running...");
                }
            };
            t3.start();
    
            // timed_waiting
            Thread t4 = new Thread("t4") {
                @Override
                public void run() {
                    synchronized (TestState.class) {
                        try {
                            Thread.sleep(1000000); 
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            t4.start();
    
            // waiting
            Thread t5 = new Thread("t5") {
                @Override
                public void run() {
                    try {
                        t2.join(); 
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            t5.start();
    
            // blocked
            Thread t6 = new Thread("t6") {
                @Override
                public void run() {
                    synchronized (TestState.class) { 
                        try {
                            Thread.sleep(1000000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            t6.start();
    
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.debug("t1 state {}", t1.getState());
            log.debug("t2 state {}", t2.getState());
            log.debug("t3 state {}", t3.getState());
            log.debug("t4 state {}", t4.getState());
            log.debug("t5 state {}", t5.getState());
            log.debug("t6 state {}", t6.getState());
            System.in.read();
        }
    }
    /*
    运行结果:
    22:00:37.048 c.TestState [t3] - running...
    22:00:37.554 c.TestState [main] - t1 state NEW
    22:00:37.556 c.TestState [main] - t2 state RUNNABLE
    22:00:37.556 c.TestState [main] - t3 state TERMINATED
    22:00:37.556 c.TestState [main] - t4 state TIMED_WAITING
    22:00:37.556 c.TestState [main] - t5 state WAITING
    22:00:37.556 c.TestState [main] - t6 state BLOCKED
    
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

    4 应用案例

    以泡壶茶喝为例,统计最少花费时间.

    洗水壶1分钟,烧开水15分钟,洗茶壶1分钟,洗茶杯2分钟,拿茶叶1分钟,泡茶.

    洗水壶1分钟
    烧开水15分钟
    泡茶
    洗茶壶1分钟
    洗茶杯2分钟
    拿茶叶1分钟
    public class Test16 {
    
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                log.debug("洗水壶");
                sleep(1);
                log.debug("烧开水");
                sleep(5);
            },"老王");
    
            Thread t2 = new Thread(() -> {
                log.debug("洗茶壶");
                sleep(1);
                log.debug("洗茶杯");
                sleep(2);
                log.debug("拿茶叶");
                sleep(1);
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.debug("泡茶");
            },"小王");
    
            t1.start();
            t2.start();
        }
    }
    /*
    运行结果:
    22:02:55.910 c.Test16 [小王] - 洗茶壶
    22:02:55.910 c.Test16 [老王] - 洗水壶
    22:02:56.935 c.Test16 [小王] - 洗茶杯
    22:02:56.935 c.Test16 [老王] - 烧开水
    22:02:58.936 c.Test16 [小王] - 拿茶叶
    22:03:01.935 c.Test16 [小王] - 泡茶
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  • 相关阅读:
    物联网AI MicroPython传感器学习 之 TDS水质检测传感器
    解决linux5.15编译时不生成boot.img 的问题
    Flutter 处理异步操作并根据异步操作状态动态构建界面的方法FutureBuilder
    Java开发全终端实战租房项目-阿里云OSS
    Java 并发高频面试题:聊聊你对 AQS 的理解?
    Android组件通信——PendingIntent(二十八)
    迷茫了3年:做完这个测试项目,我终于决定辞职
    【MindSpore】【图片加载】加载RGB-D图片失败
    leetcode 1770. Maximum Score from Performing Multiplication Operations(乘积的最大分数)
    Redis持久化
  • 原文地址:https://blog.csdn.net/ABestRookie/article/details/125419764