Skip to content

线程的生命周期

在 Java 中线程从新建到关闭会经过不同的状态,将线程从新建到关闭作为一个生命周期,在 Java 中整个线程的生命周期有 6 种状态。

线程状态类型

在 JDK 的 Thread 类,存在 State 枚举类,包含了线程的 6 种状态。

java
    public enum State {
        
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
    }
  1. NEW

    新建 Thread,还没有开始执行。

  2. RUNNABLE

    可运行的 Thread,包含准备运行(运行但未分配到CPU)和正在运行的。

  3. BLOCKED

    线程被阻塞,等待资源锁的线程。

  4. WAITING

    正在无限期的等待其它线程执行。

  5. TIMED_WAITING

    在有限时间内等待其它线程执行。

  6. TERMINATED

    线程执行完毕。


java
    /**
     * 测试线程状态枚举
     */
    @Test
    public void testStateEmun() {
        //线程状态枚举类
        Thread.State[] values = Thread.State.values();
        for (Thread.State value : values) {
            String name = value.name();
            System.out.println(name);
        }
    }

线程状态切换

在一定程度上是不可逆转的,比如线程执行之后不会回到 NEW 状态,线程关闭之后(TERMINATED)也不会回到 RUNNABLE 状态。

image-20250528161936705

1. NEW

线程类 Thread 在创建之后的状态为 NEW


java
    /**
     * 测试NEW
     */
    @Test
    public void testNewState() {
        Thread thread = new Thread(() -> {
        });
        //未运行的线程状态是NEW
        Thread.State state = thread.getState();
        System.out.println(state.name());
    }

2. RUNNABLE

在线程处于新建就绪状态(NEW),调用 start() 方法开始执行,进入运行状态(RUNNABLE)。

注意此过程不可逆,线程进入运行状态(RUNNABLE)后,无法回到新建状态(NEW)。


java
    @Test
    public void testRunnableState() {
        Thread thread = new Thread(() -> {
        });
        //调用run方法,并不会启动线程,此时运行状态还是NEW
//        thread.run();
        //线程启动后,运行状态为RUNNABLE
        thread.start();
        Thread.State state = thread.getState();
        System.out.println(state.name());
    }

3. BLOCKED

线程在遇到需要临界资源的时候,若没有竞争到临界资源,线程就从运行状态(RUNNABLE)进入到阻塞状态(BLOCKED),当线程竞争到临界资源之后会从阻塞状态回归到运行状态。


java
    /**
     * 测试BLOCKED
     */
    @Test
    public void testBlockedState() {
        Object object = new Object();
        Runnable runnable = () -> {
            synchronized (object) {
                while (true) {
                    //线程独占资源,谁先抢到谁运行,未抢到的会阻塞
                }
            }
        };
        Thread threadOne = new Thread(runnable);
        Thread threadTwo = new Thread(runnable);
        //线程one获取资源,状态为:RUNNABLE
        threadOne.start();
        //线程two被阻塞,状态为:BLOCKED
        threadTwo.start();
        System.out.println("threadOne name :" + threadOne.getName() + "; state :" + threadOne.getState().name());
        System.out.println("threadTwo name :" + threadTwo.getName() + "; state :" + threadTwo.getState().name());
    }

4. WAITING

有三种方法可以使线程从运行状态(RUNNABLE)到等待状态(WAITING)。

  • object.wait()

  • thread.join()

  • LockSupport.park()

对应的 WAITING -> RUNNABLE 状态,有以下几种方式。

  • notify()
  • notifyAll()
  • LockSupport.unpark()

java
    /**
     * 测试WAITING
     * 使用object.wait()
     */
    @SneakyThrows
    @Test
    public void testWaitingState() {
        //对象锁
        Object object = new Object();
        //第一个线程等待
        Thread threadOne = new Thread(() -> {
            try {
                Thread.sleep(1000);
                synchronized (object) {
                    System.out.println("threadOne wait!!!");
                    //threadOne进行等待
                    object.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("threadOne被唤醒之后继续执行!");
            System.out.println("threadOne end!");
        });

        //第二个线程通知
        Thread threadTwo = new Thread(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("threadOne state:" + threadOne.getState().name());
                synchronized (object) {
                    System.out.println("threadTwo notify threadOne!!!");
                    //唤醒threadOne(并不直接释放锁,而是让threadOne开始竞争锁)
                    object.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("threadTwo notify threadOne 后并没有直接退出,而是继续执行!!!");
        });
        threadOne.start();
        threadTwo.start();
        Thread.sleep(10000);
    }

    /**
     * 测试WAITING
     * 使用thread.join()
     */
    @SneakyThrows
    @Test
    public void testWaitingStateJoin() {
        //第一个线程睡眠
        Thread threadOne = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //第二个线程等待第一个线程
        Thread threadTwo = new Thread(() -> {
            try {
                //等待ThreadOne执行完毕
                threadOne.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadOne.start();
        threadTwo.start();
        Thread.sleep(1000);
        System.out.println("threadTwo state:"+threadTwo.getState().name());
        Thread.sleep(10000);
    }

    /**
     * 测试WAITING
     * 使用LockSupport.park()
     */
    @SneakyThrows
    @Test
    public void testWaitingStateLockSupport() {
        //第一个线程阻塞
        Thread threadOne = new Thread(() -> {
            //开始阻塞
            LockSupport.park();
            System.out.println("threadOne unpark!!!");
            while (true){}
        });
        //第二个线程等待第一个线程
        Thread threadTwo = new Thread(() -> {
            try {
                Thread.sleep(3000);
                //取消阻塞(RUNNABLE->WAITING)
                LockSupport.unpark(threadOne);
                Thread.sleep(1000);
                System.out.println("threadOne unpark state:"+threadOne.getState().name());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        threadOne.start();
        threadTwo.start();
        Thread.sleep(1000);
        System.out.println("threadOne state:"+threadOne.getState().name());
        Thread.sleep(10000);
    }

5. TIME_WAITING

有多种方式可以使线程从运行状态(RUNNABLE)到有限等待状态(TIME_WAITING)。

  • thread.sleep(long millis)
  • wait(int timeout)
  • thread.join(long millis)
  • LockSupport.parkNanos(long nanos)
  • LockSupport.parkUntil()

对应的 TIME_WAITING -> RUNNABLE 状态,有以下几种方式。

  • 自然到期。
  • notify()
  • notifyAll()
  • LockSupport.unpark()

java
    /**
     * 测试TIME_WAITING
     */
    @SneakyThrows
    @Test
    public void testTimeWaitintState() {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        Thread.sleep(1000);
        //TIMED_WAITING
        System.out.println("thread state:" + thread.getState().name());
        Thread.sleep(10000);
    }

6. TERMINATED

线程在执行完成之后会从运行状态(RUNNABLE)进入到关闭状态(TERMINATED)。

注意此过程不可逆,线程关闭之后(TERMINATED)不会回到 RUNNABLE 状态。


java
    /**
     * 测试TERMINATED
     */
    @SneakyThrows
    @Test
    public void testTerminatedState() {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        Thread.sleep(1000);
        System.out.println(thread.getState().name());
    }

参考链接

知乎-flydean-java中线程的生命周期