java线程状态

图形说明:

Thread.State源码注释:

java 复制代码
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;
}

代码示例:
NEW状态:

java 复制代码
public class ThreadState {

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread();
        System.out.println(thread.getState());
    }
}

结果:

RUNNABLE状态:

java 复制代码
    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());
    }
}

结果:

WAITING状态:

java 复制代码
    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());
    }

结果:

join方法代码:

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

TIMED WAITING状态:

java 复制代码
    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());
    }

结果:

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方法,
在此等待获取锁的过程线程都处于阻塞状态。

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就豁然开朗)。
java 复制代码
    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()));
    }

结果:

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

TERMINATED状态:

java 复制代码
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(() -> {

        });
        thread.start();
        Thread.sleep(50);
        System.out.println(thread.getState());
    }

结果:

相关推荐
爱编程的小生23 分钟前
Easyexcel(7-自定义样式)
java·excel
AI人H哥会Java1 小时前
【JAVA】Java基础—面向对象编程:常用API与数据结构—集合框架(List、Set、Map等)
java·开发语言
shepherd枸杞泡茶1 小时前
C# 数据结构之【队列】C#队列
开发语言·数据结构·c#
神仙别闹2 小时前
基于C语言实现的(控制台)校园导航系统
java·服务器·c语言
scoone2 小时前
C++中的原子操作:原子性、内存顺序、性能优化与原子变量赋值
开发语言·c++
轩情吖2 小时前
模拟实现Bash
linux·c语言·开发语言·c++·后端·bash·环境变量
路在脚下@2 小时前
Spring MVC
java·spring
J不A秃V头A2 小时前
IntelliJ IDEA 中,自动删除无用导包
java·intellij-idea
小_太_阳2 小时前
idea_卸载与安装
java·ide·intellij-idea
旧故新长2 小时前
版本控制和idea简体中文教程
java·开发语言·intellij-idea