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());
    }

结果:

相关推荐
她似晚风般温柔7895 分钟前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
从心归零6 分钟前
sshj使用代理连接服务器
java·服务器·sshj
咩咩大主教6 分钟前
C++基于select和epoll的TCP服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·io多路复用
FuLLovers36 分钟前
2024-09-13 冯诺依曼体系结构 OS管理 进程
linux·开发语言
IT毕设梦工厂1 小时前
计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战
java·spring boot·python·django·毕业设计·源码·课程设计
everyStudy2 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
luthane2 小时前
python 实现average mean平均数算法
开发语言·python·算法
Ylucius2 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
凡人的AI工具箱2 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
sleP4o2 小时前
Python操作MySQL
开发语言·python·mysql