• java线程状态


    图形说明:
    在这里插入图片描述
    Thread.State源码注释:

    public enum State {
        /**
         *  新生状态:线程对象创建,但是还未start()
         */
        NEW,
    
        /**
         * 线程处于可运行状态,但是这个可运行状态并不代表线程一定在虚拟机中执行。
         * 需要等待从操作系统获取到资源(比如处理器时间片),才能真正的去运行
         */
        RUNNABLE,
    
        /**
         * 当前线程处于阻塞状态,正在等待另一个线程的monitor lock释放,才进入synchronized代码块或方法
         */
        BLOCKED,
    
        /**
         * 调用Object#wait() 、 Thread.join方法后当前线程处于等待状态,
         * 等待其他的线程执行特定的动作,才能从等待状态退出。
         * 比如:Object.wait()的线程需要等待其他线程调用Object.notify()、Object.notifyAll()才能退出
         * 比如:调用了Thread.join()的线程需要等待指定的线程执行完成才能退出等待状态。
         */
        WAITING,
    
        /**
         * 进入特定时间内的等待状态,等待一段指定的时间sleep(timed)、wait(timed)或者等待Thread.join(timed)的时间.
         * 到达指定时间点自动退出恢复到RUNNABLE状态
         */
        TIMED_WAITING,
    
        /**
          * 线程结束状态
         */
        TERMINATED;
    }
    
    • 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

    代码示例:
    NEW状态:

    public class ThreadState {
    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread();
            System.out.println(thread.getState());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果:
    在这里插入图片描述

    RUNNABLE状态:

    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(()-> {
                while (true){
                    Thread.yield();
                }
            });
            thread.start();
            Thread.sleep(2000);
            System.out.println(thread.getState());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果:
    在这里插入图片描述

    WAITING状态:

    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(()-> {
                LockSupport.park();
                while (true){
                    Thread.yield();
                }
            });
            thread.start();
            Thread.sleep(50);
            System.out.println(thread.getState());
            LockSupport.unpark(thread);
            Thread.sleep(50);
            System.out.println(thread.getState());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果:
    在这里插入图片描述
    join方法代码:
    在这里插入图片描述
    可见Thread#join()是在线程实例存活的时候总是调用Object#wait()方法,也就是必须在线程执行完毕isAlive()为false(意味着线程生命周期已经终结)的时候才会解除阻塞。

    TIMED WAITING状态:

    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(()-> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    //ignore
                }
            });
            thread.start();
            thread.notify();
            Thread.sleep(50);
            System.out.println(thread.getState());
            Thread.sleep(1000);
            System.out.println(thread.getState());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    结果:
    在这里插入图片描述
    BLOCKED状态:
    BLOCKED状态也就是阻塞状态,该状态下的线程不会被分配CPU执行时间。线程的状态为BLOCKED的时候有两种可能的情况:

    A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method

    1.线程正在等待一个监视器锁,只有获取监视器锁之后才能进入synchronized代码块或者synchronized方法,
    在此等待获取锁的过程线程都处于阻塞状态。
    
    • 1
    • 2

    reenter a synchronized block/method after calling Object#wait()

    2.线程X步入synchronized代码块或者synchronized方法后(此时已经释放监视器锁)调用Object#wait()方法之后进行阻塞,
    当接收其他线程T调用该锁对象Object#notify()/notifyAll(),但是线程T尚未退出它所在的synchronized代码块或者synchronized方法,
    那么线程X依然处于阻塞状态(注意API注释中的reenter,理解它场景2就豁然开朗)。
    
    • 1
    • 2
    • 3
    
        private static final Object MONITOR = new Object();
        private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
        public static void main(String[] args) throws Exception {
            System.out.printf("[%s]-begin...%n", F.format(LocalDateTime.now()));
            Thread thread1 = new Thread(() -> {
                synchronized (MONITOR) {
                    System.out.printf("[%s]-thread1 got monitor lock...%n", F.format(LocalDateTime.now()));
                    try {
                        Thread.sleep(1000);
                        MONITOR.wait();
                    } catch (InterruptedException e) {
                        //ignore
                    }
                    System.out.printf("[%s]-thread1 exit waiting...%n", F.format(LocalDateTime.now()));
                }
            });
            Thread thread2 = new Thread(() -> {
                synchronized (MONITOR) {
                    System.out.printf("[%s]-thread2 got monitor lock...%n", F.format(LocalDateTime.now()));
                    try {
                        MONITOR.notify();
             //这个时候thread2已经释放了MONITOR锁,thread1已经被唤醒,但是因为thread2还在占用MONITOR,所以thread1是blocked状态
             //对应 reenter a synchronized block/method after calling Object#wait()
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        //ignore
                    }
                    System.out.printf("[%s]-thread2 releases monitor lock...%n", F.format(LocalDateTime.now()));
                }
            });
            thread1.start();
            thread2.start();
        // 这里故意让主线程sleep 1500毫秒从而让thread2调用了Object#notify()并且尚未退出同步代码块,确保thread1调用了Object#wait()
            Thread.sleep(1500);  
            System.out.println(thread1.getState());
            System.out.printf("[%s]-end...%n", F.format(LocalDateTime.now()));
        }
    
    • 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

    结果:
    在这里插入图片描述
    源码的注释说的就是上述测试的情况,虽然调用了notify方法,但是被唤醒的线程并不会进入RUNNABLE状态,需要等thread2释放锁以后重新参与锁竞争;
    在这里插入图片描述

    TERMINATED状态:

    
        public static void main(String[] args) throws Exception {
            Thread thread = new Thread(() -> {
    
            });
            thread.start();
            Thread.sleep(50);
            System.out.println(thread.getState());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果:
    在这里插入图片描述

  • 相关阅读:
    基于猕猴Spike运动解码的不同解码方法性能对比
    rancher容器内获取真实客户端请求IP地址【超简洁步骤】
    Ajax系列之文件上传图片即时预览
    java-初识Servlet,Tomcat,JDBC
    Android11.0 修改设备名、型号、厂商
    接口获取数据,转成JSONOBJECT
    redis 介绍
    vulnhub靶场之Chronos:1
    基于HTML5+JavaScript实现的网页录屏器设计
    【Azure APIM】验证APIM删除后的恢复步骤
  • 原文地址:https://blog.csdn.net/weixin_43337246/article/details/132638624