以下是针对线程状态的极其详细讲解。本篇将按照线程的六种状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED)逐一展开,每个状态包括定义、原因、代码案例、练习,以及易错点、混淆点和容易搞错的点。

线程状态概述

线程是程序执行的最小单位,其状态反映了线程在生命周期中的行为。理解这些状态对调试并发问题、避免死锁和提高性能至关重要。Java中,线程状态通过Thread.State枚举表示,包括:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。每个状态都有特定触发条件和行为,下面我们逐一深入讲解。


1. NEW(新建)

定义与原因

NEW状态表示线程对象已被创建(例如,通过new Thread()),但尚未调用start()方法启动。此时,线程只是内存中的一个对象,没有分配系统资源(如CPU时间片),不会执行run()方法。只有调用start()后,线程才进入RUNNABLE状态。

代码案例
public class NewStateExample {
    public static void main(String[] args) {
        // 创建线程对象,但未调用start()
        Thread thread = new Thread(() -> {
            System.out.println("线程运行中");
        });
        
        // 打印线程状态:应为 NEW
        System.out.println("线程状态: " + thread.getState()); // 输出: NEW
    }
}

运行此代码,线程状态为NEW,因为start()未被调用。

练习

每个练习旨在加深理解,请先尝试解答,再参考解释。

  1. 练习1:基础状态检查
    编写代码创建两个线程对象,但不调用start()。打印它们的线程状态。确认状态是否为NEW。

    // 示例代码框架
    Thread t1 = new Thread(() -> {});
    Thread t2 = new Thread(() -> {});
    System.out.println("t1状态: " + t1.getState());
    System.out.println("t2状态: " + t2.getState());
    

    解释:状态应为NEW。易错点:误以为线程创建后自动启动。

  2. 练习2:方法调用影响
    在NEW状态下,线程能否调用run()方法?如果可以,调用后状态会变吗?编写代码测试。

    Thread thread = new Thread(() -> {
        System.out.println("run()方法执行");
    });
    thread.run(); // 直接调用run()
    System.out.println("状态: " + thread.getState());
    

    解释:直接调用run()不会改变状态(仍为NEW),因为它只是普通方法调用,而非启动线程。易错点:混淆run()start(),以为run()能启动线程。

  3. 练习3:状态转换模拟
    创建一个线程对象,先打印状态(应为NEW),然后调用start(),再打印状态。观察变化。

    Thread thread = new Thread(() -> {});
    System.out.println("start前状态: " + thread.getState()); // NEW
    thread.start();
    System.out.println("start后状态: " + thread.getState()); // 可能为RUNNABLE
    

    解释:调用start()后状态变为RUNNABLE。易错点:在多线程环境中,状态打印可能受调度影响,不一定是即时变化。

  4. 练习4:错误场景分析
    假设代码中多次调用start()方法(例如:thread.start(); thread.start();)。会发生什么?状态如何变化?

    Thread thread = new Thread(() -> {});
    thread.start();
    thread.start(); // 第二次调用start()
    

    解释:抛出IllegalThreadStateException,因为线程不能重复启动。状态在第一次start()后变为RUNNABLE或TERMINATED,但不会回到NEW。易错点:忽略线程状态的生命周期,以为可以重复启动。

  5. 练习5:资源占用问题
    在NEW状态下,线程是否占用系统资源(如CPU或内存)?编写代码创建1000个NEW线程,观察内存使用(可用Runtime.getRuntime().totalMemory())。

    public class ResourceTest {
        public static void main(String[] args) {
            for (int i = 0; i < 1000; i++) {
                new Thread(() -> {}); // 只创建,不start
            }
            System.out.println("内存占用: " + Runtime.getRuntime().totalMemory());
        }
    }
    

    解释:NEW线程占用内存(对象开销),但不占用CPU。易错点:误以为NEW线程无开销,导致内存泄漏。

易错点与混淆点
  • 易错点:NEW状态容易被忽略,因为线程不执行任何任务。开发者可能在创建线程后忘记调用start(),导致程序逻辑错误。
  • 混淆点:NEW状态与“未初始化”混淆。NEW线程对象已初始化,但未激活。与RUNNABLE混淆,因为两者都涉及线程对象存在。
  • 容易搞错的点:直接调用run()方法不会改变状态,它只是同步执行代码块,而非启动新线程。线程启动必须通过start()

2. RUNNABLE(可运行)

定义与原因

RUNNABLE状态表示线程已启动(调用start()),正在运行或等待CPU时间片。在Java中,RUNNABLE统一表示就绪(Ready)和运行(Running)状态:就绪时线程等待调度,运行时占用CPU执行。操作系统层面,就绪和运行是分开的,但Java API只暴露RUNNABLE。线程可通过yield()让出CPU,但状态不变。

代码案例
public class RunnableStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                // 模拟运行
            }
        });
        thread.start();
        System.out.println("线程状态: " + thread.getState()); // 输出: RUNNABLE
    }
}

线程启动后进入RUNNABLE状态,可能在运行或就绪。

练习
  1. 练习1:状态打印时机
    启动一个线程,在循环中打印状态。观察状态是否总为RUNNABLE。

    Thread thread = new Thread(() -> {
        while (true) { /* 空循环 */ }
    });
    thread.start();
    for (int i = 0; i < 5; i++) {
        System.out.println("状态: " + thread.getState()); // 应为RUNNABLE
        Thread.sleep(100); // 主线程睡眠,让子线程运行
    }
    

    解释:状态始终为RUNNABLE。易错点:误以为在循环中状态会变化,但RUNNABLE涵盖就绪和运行。

  2. 练习2:CPU竞争模拟
    创建两个高优先级线程,竞争CPU。打印状态,观察调度。

    Thread t1 = new Thread(() -> { while(true) {} });
    Thread t2 = new Thread(() -> { while(true) {} });
    t1.setPriority(Thread.MAX_PRIORITY);
    t2.setPriority(Thread.MAX_PRIORITY);
    t1.start();
    t2.start();
    System.out.println("t1状态: " + t1.getState()); // RUNNABLE
    System.out.println("t2状态: " + t2.getState()); // RUNNABLE
    

    解释:两者均为RUNNABLE,但操作系统可能切换运行状态。易错点:以为优先级高的线程总在运行状态。

  3. 练习3:yield()方法影响
    在线程中调用Thread.yield(),打印状态。状态会变吗?

    Thread thread = new Thread(() -> {
        while (true) {
            Thread.yield(); // 让出CPU
        }
    });
    thread.start();
    System.out.println("状态: " + thread.getState()); // RUNNABLE
    

    解释:状态仍为RUNNABLE,yield()只是提示调度器让出CPU,不改变状态。易错点:误以为yield()使线程进入WAITING。

  4. 练习4:多线程并发
    启动10个线程,每个打印自己的状态。所有状态应为RUNNABLE吗?

    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            System.out.println("状态: " + Thread.currentThread().getState());
        }).start();
    }
    

    解释:输出可能显示RUNNABLE,但受调度影响,打印时线程可能在运行或就绪。易错点:在多核CPU上,多个线程可同时运行,状态打印可能不一致。

  5. 练习5:状态与性能
    编写代码,测量线程在RUNNABLE状态下的CPU占用(可用ThreadMXBean)。观察就绪和运行的区别。

    import java.lang.management.ThreadMXBean;
    import java.lang.management.ManagementFactory;
    
    public class CpuUsage {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(() -> { while(true) {} });
            thread.start();
            ThreadMXBean bean = ManagementFactory.getThreadMXBean();
            long cpuTime = bean.getThreadCpuTime(thread.getId());
            System.out.println("CPU时间: " + cpuTime); // 非零表示运行过
            System.out.println("状态: " + thread.getState()); // RUNNABLE
        }
    }
    

    解释:RUNNABLE状态不区分就绪和运行,但CPU时间非零表示线程曾运行。易错点:混淆状态和实际CPU占用。

易错点与混淆点
  • 易错点:RUNNABLE状态在Java中统一表示,但开发者可能误以为线程总在运行,忽略就绪状态。导致性能优化时忽略调度开销。
  • 混淆点:与BLOCKED混淆,因为两者都可能“等待”,但RUNNABLE是主动等待CPU,BLOCKED是被动等待锁。
  • 容易搞错的点:线程在I/O操作(如文件读写)时状态仍为RUNNABLE,因为I/O在Java中可能不阻塞线程(使用NIO时)。操作系统层可能阻塞,但Java状态不变。

3. BLOCKED(阻塞)

定义与原因

BLOCKED状态表示线程因等待监视器锁(如synchronized关键字)而阻塞。只有当线程试图进入synchronized代码块或方法,但锁被其他线程持有时,才进入此状态。一旦锁释放,线程自动转为RUNNABLE。注意:BLOCKED仅针对synchronized锁,不适用于其他锁机制(如ReentrantLock)。

代码案例
public class BlockedStateExample {
    public static final Object lock = new Object();
    
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                while (true) {} // 持有锁不释放
            }
        });
        Thread t2 = new Thread(() -> {
            synchronized (lock) { // 等待锁
                System.out.println("t2获得锁");
            }
        });
        
        t1.start();
        t2.start();
        System.out.println("t2状态: " + t2.getState()); // 可能为BLOCKED
    }
}

t2在等待锁时进入BLOCKED状态。

练习
  1. 练习1:锁竞争
    创建两个线程竞争同一锁。打印等待线程的状态。

    Object lock = new Object();
    Thread t1 = new Thread(() -> {
        synchronized (lock) {
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        }
    });
    Thread t2 = new Thread(() -> {
        synchronized (lock) { // 等待锁
        }
    });
    t1.start();
    t2.start();
    Thread.sleep(100); // 让t1先运行
    System.out.println("t2状态: " + t2.getState()); // BLOCKED
    

    解释:t2在等待锁时状态为BLOCKED。易错点:未确保t1先获得锁,导致状态打印错误。

  2. 练习2:错误锁释放
    线程在BLOCKED状态下,如何被唤醒?修改代码,让t1释放锁后观察t2状态变化。

    // 同上代码,但t1 sleep后释放锁
    // t2状态在t1释放后变为RUNNABLE
    

    解释:锁释放后,t2自动转为RUNNABLE。易错点:误以为需要显式唤醒(如notify()),但BLOCKED是自动恢复。

  3. 练习3:BLOCKED vs WAITING
    使用wait()方法,线程状态是什么?编写代码对比。

    Object lock = new Object();
    Thread t1 = new Thread(() -> {
        synchronized (lock) {
            try { lock.wait(); } catch (InterruptedException e) {} // 调用wait()
        }
    });
    t1.start();
    Thread.sleep(100);
    System.out.println("t1状态: " + t1.getState()); // WAITING, not BLOCKED
    

    解释:调用wait()进入WAITING状态,而非BLOCKED。易错点:混淆BLOCKED(锁竞争)和WAITING(主动等待)。

  4. 练习4:死锁检测
    创建死锁场景:两个线程互相等待锁。打印状态,识别BLOCKED线程。

    Object lock1 = new Object();
    Object lock2 = new Object();
    Thread t1 = new Thread(() -> {
        synchronized (lock1) {
            synchronized (lock2) {} // 等待lock2
        }
    });
    Thread t2 = new Thread(() -> {
        synchronized (lock2) {
            synchronized (lock1) {} // 等待lock1
        }
    });
    t1.start();
    t2.start();
    Thread.sleep(1000);
    System.out.println("t1状态: " + t1.getState()); // BLOCKED
    System.out.println("t2状态: " + t2.getState()); // BLOCKED
    

    解释:两者均BLOCKED,形成死锁。易错点:死锁时线程永久BLOCKED,需外部干预。

  5. 练习5:非synchronized锁
    使用ReentrantLock代替synchronized,线程在等待锁时状态是什么?

    import java.util.concurrent.locks.ReentrantLock;
    ReentrantLock lock = new ReentrantLock();
    Thread t1 = new Thread(() -> {
        lock.lock(); // 持有锁
        while (true) {}
    });
    Thread t2 = new Thread(() -> {
        lock.lock(); // 等待锁
    });
    t1.start();
    t2.start();
    System.out.println("t2状态: " + t2.getState()); // WAITING, 非BLOCKED
    

    解释ReentrantLock的等待使线程进入WAITING状态(通过LockSupport.park()),而非BLOCKED。易错点:以为所有锁机制都导致BLOCKED状态。

易错点与混淆点
  • 易错点:BLOCKED状态只发生在synchronized锁竞争时。开发者可能在其他等待场景(如I/O)误判为BLOCKED。
  • 混淆点:与WAITING状态混淆,因为两者都涉及“等待”,但BLOCKED是自动恢复的锁等待,WAITING需要显式唤醒。
  • 容易搞错的点:在ReentrantLockCondition上等待时,状态是WAITING或TIMED_WAITING,不是BLOCKED。忽略这点会导致调试错误。

4. WAITING(等待)

定义与原因

WAITING状态表示线程因调用无期限等待方法而暂停,例如Object.wait()Thread.join()LockSupport.park()。线程进入此状态后,不会消耗CPU资源,必须由其他线程显式唤醒(如notify()unpark())。WAITING常用于线程间协调,如生产者-消费者模型。

代码案例
public class WaitingStateExample {
    public static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    lock.wait(); // 进入WAITING
                } catch (InterruptedException e) {}
            }
        });
        thread.start();
        Thread.sleep(100); // 确保thread进入wait
        System.out.println("线程状态: " + thread.getState()); // WAITING
    }
}

线程调用wait()后进入WAITING状态。

练习
  1. 练习1:wait()方法使用
    线程调用wait()后,状态如何?编写代码唤醒它,观察状态变化。

    Object lock = new Object();
    Thread t = new Thread(() -> {
        synchronized (lock) {
            try { lock.wait(); } catch (InterruptedException e) {}
            System.out.println("唤醒后");
        }
    });
    t.start();
    Thread.sleep(100);
    System.out.println("状态: " + t.getState()); // WAITING
    synchronized (lock) {
        lock.notify(); // 唤醒
    }
    Thread.sleep(100);
    System.out.println("状态: " + t.getState()); // RUNNABLE或TERMINATED
    

    解释:唤醒后状态变为RUNNABLE。易错点:忘记在同步块内调用notify(),导致唤醒失败。

  2. 练习2:join()方法
    主线程调用子线程的join(),状态是什么?

    Thread child = new Thread(() -> {
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
    });
    child.start();
    child.join(); // 主线程调用join()
    // 在主线程中打印自身状态?
    System.out.println("主线程状态: " + Thread.currentThread().getState()); // RUNNABLE
    

    解释join()使调用线程(主线程)进入WAITING状态,等待子线程结束。但打印自身状态时为RUNNABLE,因为join()内部实现使用WAITING。易错点:误以为join()改变的是子线程状态。

  3. 练习3:永久等待风险
    编写代码,线程wait()但无唤醒逻辑。状态会变吗?如何避免死锁?

    Object lock = new Object();
    Thread t = new Thread(() -> {
        synchronized (lock) {
            try { lock.wait(); } catch (InterruptedException e) {}
        }
    });
    t.start();
    // 无唤醒代码
    Thread.sleep(2000);
    System.out.println("状态: " + t.getState()); // 仍为WAITING
    

    解释:状态永久WAITING,导致线程泄漏。易错点:忘记设计唤醒机制。

  4. 练习4:多线程协调
    实现生产者-消费者模型,生产者wait()当缓冲区满。打印状态确认WAITING。

    import java.util.Queue;
    import java.util.LinkedList;
    Queue<Integer> buffer = new LinkedList<>();
    int maxSize = 1;
    Object lock = new Object();
    
    Thread producer = new Thread(() -> {
        synchronized (lock) {
            while (buffer.size() == maxSize) {
                try { lock.wait(); } catch (InterruptedException e) {} // WAITING
            }
            buffer.add(1);
            lock.notify();
        }
    });
    producer.start();
    // 类似创建consumer线程
    

    解释:当缓冲区满时,生产者进入WAITING。易错点:未在循环中检查条件(虚假唤醒问题)。

  5. 练习5:LockSupport.park()
    使用LockSupport.park()使线程进入WAITING。如何唤醒?

    Thread thread = new Thread(() -> {
        LockSupport.park(); // 进入WAITING
    });
    thread.start();
    Thread.sleep(100);
    System.out.println("状态: " + thread.getState()); // WAITING
    LockSupport.unpark(thread); // 唤醒
    

    解释park()进入WAITING,unpark()唤醒。易错点:unpark()可在park()前调用,防止永久等待。

易错点与混淆点
  • 易错点:WAITING状态需要显式唤醒,开发者可能忘记调用notify()unpark(),导致线程永久挂起。
  • 混淆点:与BLOCKED混淆,因为两者都“等待”,但WAITING是主动调用等待方法,BLOCKED是锁竞争被动等待。
  • 容易搞错的点Thread.join()使调用线程进入WAITING,而非被join的线程。忽略这点会导致状态判断错误。

5. TIMED_WAITING(计时等待)

定义与原因

TIMED_WAITING状态表示线程因调用有时间限制的等待方法而暂停,例如Thread.sleep(long millis)Object.wait(long timeout)Thread.join(long millis)。线程在指定时间后自动唤醒(或提前被中断),无需显式唤醒。常用于定时任务或超时控制。

代码案例
public class TimedWaitingStateExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000); // 进入TIMED_WAITING
            } catch (InterruptedException e) {}
        });
        thread.start();
        Thread.sleep(100); // 确保thread进入sleep
        System.out.println("线程状态: " + thread.getState()); // TIMED_WAITING
    }
}

线程sleep()时进入TIMED_WAITING状态。

练习
  1. 练习1:sleep()方法
    线程调用sleep(1000),打印状态。时间结束后状态变化?

    Thread t = new Thread(() -> {
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
    });
    t.start();
    Thread.sleep(100);
    System.out.println("状态: " + t.getState()); // TIMED_WAITING
    Thread.sleep(2000);
    System.out.println("状态: " + t.getState()); // TERMINATED
    

    解释:睡眠结束后状态变为TERMINATED(如果run()结束)。易错点:单位错误(sleep参数是毫秒)。

  2. 练习2:wait(timeout)
    使用wait(500),状态如何?与sleep()对比。

    Object lock = new Object();
    Thread t = new Thread(() -> {
        synchronized (lock) {
            try { lock.wait(500); } catch (InterruptedException e) {} // TIMED_WAITING
        }
    });
    t.start();
    Thread.sleep(100);
    System.out.println("状态: " + t.getState()); // TIMED_WAITING
    

    解释:状态为TIMED_WAITING。易错点:wait(timeout)必须在同步块内调用,否则抛IllegalMonitorStateException

  3. 练习3:join(timeout)
    主线程调用子线程的join(1000),状态变化?

    Thread child = new Thread(() -> {
        try { Thread.sleep(2000); } catch (InterruptedException e) {}
    });
    child.start();
    child.join(1000); // 主线程TIMED_WAITING
    System.out.println("主线程状态: " + Thread.currentThread().getState()); // RUNNABLE
    

    解释join(timeout)使调用线程进入TIMED_WAITING,但打印自身状态时为RUNNABLE。易错点:混淆超时和实际线程结束。

  4. 练习4:中断处理
    线程在TIMED_WAITING时被中断(interrupt()),状态如何?编写代码测试。

    Thread t = new Thread(() -> {
        try { Thread.sleep(1000); } catch (InterruptedException e) {
            System.out.println("中断捕获");
        }
    });
    t.start();
    Thread.sleep(100);
    t.interrupt(); // 中断
    Thread.sleep(100);
    System.out.println("状态: " + t.getState()); // RUNNABLE或TERMINATED
    

    解释:中断后线程唤醒,状态变为RUNNABLE。易错点:未处理InterruptedException,导致行为未定义。

  5. 练习5:定时任务模拟
    创建线程每秒执行任务,使用sleep(1000)。打印状态确认TIMED_WAITING。

    Thread timer = new Thread(() -> {
        while (true) {
            System.out.println("任务执行");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
        }
    });
    timer.start();
    Thread.sleep(1500);
    System.out.println("状态: " + timer.getState()); // TIMED_WAITING (在sleep期间)
    

    解释:在sleep()期间状态为TIMED_WAITING。易错点:循环中使用sleep()可能导致精度问题。

易错点与混淆点
  • 易错点:时间参数单位错误(如秒vs毫秒),导致等待时间不符预期。sleep()不会释放锁,而wait(timeout)会。
  • 混淆点:与WAITING混淆,因为两者都“等待”,但TIMED_WAITING有超时机制,自动唤醒。
  • 容易搞错的点Thread.join(timeout)如果超时,线程未结束,调用线程仍继续执行,但被join的线程可能还在运行。

6. TERMINATED(终止)

定义与原因

TERMINATED状态表示线程已执行完毕(run()方法正常结束)或因未捕获异常退出。线程进入此状态后,不能被重启(调用start()会抛异常),系统资源被释放。线程对象仍存在,但状态不可变。

代码案例
public class TerminatedStateExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            // run()方法执行完毕
        });
        thread.start();
        thread.join(); // 等待结束
        System.out.println("线程状态: " + thread.getState()); // TERMINATED
    }
}

线程结束后状态为TERMINATED。

练习
  1. 练习1:正常结束
    线程执行简单任务后结束。打印状态。

    Thread t = new Thread(() -> {});
    t.start();
    t.join();
    System.out.println("状态: " + t.getState()); // TERMINATED
    

    解释:状态为TERMINATED。易错点:未使用join()确保线程结束,导致状态打印过早。

  2. 练习2:异常终止
    线程抛出未捕获异常,状态如何?

    Thread t = new Thread(() -> {
        throw new RuntimeException("错误");
    });
    t.start();
    t.join();
    System.out.println("状态: " + t.getState()); // TERMINATED
    

    解释:未捕获异常导致TERMINATED。易错点:忽略异常处理,线程静默终止。

  3. 练习3:重启尝试
    线程终止后,调用start()方法。会发生什么?

    Thread t = new Thread(() -> {});
    t.start();
    t.join();
    t.start(); // 第二次start
    

    解释:抛出IllegalThreadStateException。易错点:误以为线程可重用。

  4. 练习4:isAlive()方法
    使用isAlive()检查线程是否存活。终止后返回什么?

    Thread t = new Thread(() -> {});
    t.start();
    t.join();
    System.out.println("isAlive: " + t.isAlive()); // false
    System.out.println("状态: " + t.getState()); // TERMINATED
    

    解释isAlive()返回false,状态为TERMINATED。易错点:混淆isAlive()和状态API。

  5. 练习5:线程池影响
    在线程池中,线程执行任务后状态如何?(模拟使用ExecutorService

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    ExecutorService pool = Executors.newSingleThreadExecutor();
    pool.execute(() -> {});
    // 线程池线程可能被重用,状态不一定是TERMINATED
    pool.shutdown();
    

    解释:线程池线程任务结束后可能回到RUNNABLE(等待新任务),不直接TERMINATED。易错点:以为所有线程结束时都TERMINATED,忽略线程池机制。

易错点与混淆点
  • 易错点:线程终止后仍尝试操作(如start()),导致异常。开发者可能未处理线程异常,导致意外终止。
  • 混淆点:与RUNNABLE混淆,因为线程结束前可能短暂处于RUNNABLE。isAlive()方法更直接判断存活。
  • 容易搞错的点:在线程池中,线程对象被重用,状态不固定;直接创建线程时,TERMINATED是最终状态。

总结与常见混淆点对比

线程状态反映了并发编程的核心行为。以下是关键混淆点总结:

  • RUNNABLE vs BLOCKED:RUNNABLE是主动等待CPU,BLOCKED是被动等待锁。I/O阻塞在Java中可能不改变状态。
  • BLOCKED vs WAITING:BLOCKED只针对synchronized锁,自动恢复;WAITING需要显式唤醒,适用于wait()park()
  • WAITING vs TIMED_WAITING:WAITING无超时,TIMED_WAITING有超时自动唤醒。sleep()是TIMED_WAITING,但不会释放锁。
  • TERMINATED:线程结束后不可重启,isAlive()为false。

本篇的讲解就在这里啦~希望堆大家有所帮助!~

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐