1. 线程状态概述

Java 线程在其生命周期中有 6 种状态,定义在 java.lang.Thread.State 枚举中:

public enum State {
    NEW,           // 新建
    RUNNABLE,      // 可运行
    BLOCKED,       // 阻塞
    WAITING,       // 等待
    TIMED_WAITING, // 计时等待
    TERMINATED     // 终止
}

2. 详细状态解析

2.1 NEW(新建状态)

线程对象被创建但尚未启动。

public class ThreadNewState {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程执行");
        });
        
        System.out.println("线程状态: " + thread.getState()); // NEW
        
        // 线程在start()之前的状态始终是NEW
        System.out.println("线程是否存活: " + thread.isAlive()); // false
        System.out.println("线程ID: " + thread.getId()); // 有ID但未启动
    }
}

特征

  • 已创建Thread对象

  • 尚未调用start()方法

  • 不消耗系统资源(仅Java对象)

2.2 RUNNABLE(可运行状态)

调用start()方法后,线程处于可运行状态。

public class ThreadRunnableState {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            // 模拟CPU密集型任务
            long sum = 0;
            for (int i = 0; i < 1000000; i++) {
                sum += i;
            }
            System.out.println("计算完成: " + sum);
        });
        
        thread.start();
        System.out.println("线程状态: " + thread.getState()); // RUNNABLE
        
        // RUNNABLE包含两种子状态:
        // 1. READY: 就绪,等待CPU分配时间片
        // 2. RUNNING: 正在CPU上执行
        
        // 获取线程信息
        System.out.println("线程名称: " + thread.getName());
        System.out.println("线程优先级: " + thread.getPriority());
        System.out.println("是否守护线程: " + thread.isDaemon());
    }
}

重要说明

  • RUNNABLE 状态包含操作系统层面的就绪运行两种状态

  • JVM 不区分这两种状态,都视为 RUNNABLE

  • 线程可能正在执行,也可能在等待CPU时间片

2.3 BLOCKED(阻塞状态)

线程等待获取监视器锁(synchronized)时进入阻塞状态。

public class ThreadBlockedState {
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("线程1获取锁,持有5秒");
                    Thread.sleep(5000); // 持有锁5秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        Thread thread2 = new Thread(() -> {
            System.out.println("线程2尝试获取锁...");
            synchronized (lock) {
                System.out.println("线程2获取到锁");
            }
        });
        
        thread1.start();
        Thread.sleep(100); // 确保thread1先获取锁
        
        thread2.start();
        Thread.sleep(100); // 确保thread2开始执行
        
        // thread2会阻塞,因为lock被thread1持有
        System.out.println("线程2状态: " + thread2.getState()); // BLOCKED
        
        thread1.join();
        thread2.join();
    }
}

触发条件

  1. 等待进入 synchronized 方法/代码块

  2. 调用 wait() 后重新进入同步块(需重新竞争锁)

  3. 等待 ReentrantLock(不同于 synchronized)

重要区别

public class BlockedVsSynchronized {
    // synchronized方式 - 会进入BLOCKED状态
    public synchronized void syncMethod() {
        // 方法体
    }
    
    // Lock接口方式 - 不会进入BLOCKED状态(而是WAITING/TIMED_WAITING)
    private final Lock lock = new ReentrantLock();
    
    public void lockMethod() {
        lock.lock();  // 如果锁被占用,线程进入WAITING状态(AQS队列)
        try {
            // 方法体
        } finally {
            lock.unlock();
        }
    }
}

2.4 WAITING(无限期等待)

线程等待其他线程的特定操作(通知或中断)。

public class ThreadWaitingState {
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("线程即将进入WAITING状态");
                    lock.wait(); // 释放锁并等待
                    System.out.println("线程被唤醒");
                } catch (InterruptedException e) {
                    System.out.println("线程被中断");
                }
            }
        });
        
        waitingThread.start();
        Thread.sleep(100); // 确保线程启动并进入wait()
        
        System.out.println("线程状态: " + waitingThread.getState()); // WAITING
        
        // 3秒后唤醒线程
        Thread.sleep(3000);
        synchronized (lock) {
            lock.notify(); // 唤醒一个等待线程
            // lock.notifyAll(); // 唤醒所有等待线程
        }
        
        waitingThread.join();
    }
}

进入WAITING的方法

  1. Object.wait() - 不设置超时

  2. Thread.join() - 不设置超时

  3. LockSupport.park() - LockSupport类

唤醒方式

  • Object.notify() / notifyAll()

  • LockSupport.unpark(thread)

  • 线程被中断(thread.interrupt()

2.5 TIMED_WAITING(计时等待)

线程等待指定的时间。

public class ThreadTimedWaitingState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("线程开始休眠3秒");
                Thread.sleep(3000); // 进入TIMED_WAITING
                
                // 或者使用带超时的wait
                // Object lock = new Object();
                // synchronized (lock) {
                //     lock.wait(3000);
                // }
            } catch (InterruptedException e) {
                System.out.println("休眠被中断");
            }
        });
        
        thread.start();
        Thread.sleep(100); // 确保线程启动
        
        System.out.println("线程状态: " + thread.getState()); // TIMED_WAITING
        
        // 监控状态变化
        for (int i = 0; i < 4; i++) {
            System.out.println("第" + i + "秒,线程状态: " + thread.getState());
            Thread.sleep(1000);
        }
        
        thread.join();
    }
}

进入TIMED_WAITING的方法

  1. Thread.sleep(millis)

  2. Object.wait(timeout)

  3. Thread.join(timeout)

  4. LockSupport.parkNanos(nanos)

  5. LockSupport.parkUntil(deadline)

与WAITING的区别

  • TIMED_WAITING:超时自动唤醒

  • WAITING:需要其他线程显式唤醒

2.6 TERMINATED(终止状态)

线程执行完毕。

public class ThreadTerminatedState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程开始执行");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程执行结束");
        });
        
        System.out.println("启动前状态: " + thread.getState()); // NEW
        System.out.println("是否存活: " + thread.isAlive()); // false
        
        thread.start();
        Thread.sleep(500);
        System.out.println("执行中状态: " + thread.getState()); // TIMED_WAITING
        System.out.println("是否存活: " + thread.isAlive()); // true
        
        thread.join(); // 等待线程结束
        System.out.println("结束后状态: " + thread.getState()); // TERMINATED
        System.out.println("是否存活: " + thread.isAlive()); // false
    }
}

线程终止的三种方式

  1. 正常结束:run()方法执行完毕

  2. 异常终止:run()方法抛出未捕获异常

  3. 强制终止:调用stop()方法(已废弃,不安全)

3. 完整状态转换图

      NEW
       ↓ (start())
   RUNNABLE ←─────────────────────────────────────────────┐
       ↓ (等待锁)                                           │
    BLOCKED ←───┐                                           │
       ↓ (获取锁)                                           │
   RUNNABLE     │                                           │
       ↓ (wait()/join()/park())                            │
    WAITING ────┼───→ RUNNABLE (notify()/notifyAll()/unpark())│
       ↓ (带超时的方法)                                      │
TIMED_WAITING ──┼───→ RUNNABLE (超时/通知/中断)              │
       ↓ (run()结束)                                       │
  TERMINATED    │                                           │
                └───────────────────────────────────────────┘
                      (中断:interrupt())

4. 状态转换详解

4.1 状态转换表

当前状态 转换条件 目标状态
NEW 调用 start() RUNNABLE
RUNNABLE 等待 synchronized 锁 BLOCKED
RUNNABLE 调用 wait() / join() / LockSupport.park() WAITING
RUNNABLE 调用 sleep() / wait(timeout) / join(timeout) TIMED_WAITING
RUNNABLE run() 执行完成 TERMINATED
BLOCKED 获取到锁 RUNNABLE
WAITING 被 notify() / notifyAll() / unpark() / interrupt() RUNNABLE
TIMED_WAITING 超时 / 被唤醒 / 中断 RUNNABLE
WAITING/TIMED_WAITING 等待过程中被中断 RUNNABLE(抛出InterruptedException)

4.2 完整状态转换示例

public class ThreadFullLifecycle {
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程完整生命周期演示 ===");
        
        Thread thread = new Thread(() -> {
            System.out.println("1. 线程启动,进入RUNNABLE状态");
            
            synchronized (lock) {
                System.out.println("2. 获取锁,执行同步代码块");
                
                try {
                    System.out.println("3. 调用wait(2000),进入TIMED_WAITING");
                    lock.wait(2000); // 释放锁,等待2秒
                    
                    System.out.println("5. 被唤醒,重新获取锁,继续执行");
                    
                    System.out.println("6. 调用wait(),进入WAITING状态");
                    lock.wait(); // 无限期等待
                    
                    System.out.println("8. 再次被唤醒");
                } catch (InterruptedException e) {
                    System.out.println("线程被中断");
                }
            }
            
            System.out.println("9. 线程执行完毕");
        });
        
        // 初始状态:NEW
        System.out.println("初始状态: " + thread.getState());
        
        // 启动线程
        thread.start();
        Thread.sleep(100);
        System.out.println("启动后状态: " + thread.getState());
        
        // 等待线程进入wait(2000)
        Thread.sleep(100);
        System.out.println("调用wait(2000)后状态: " + thread.getState());
        
        // 等待2.1秒(超过wait超时时间)
        Thread.sleep(2100);
        System.out.println("wait(2000)超时后状态: " + thread.getState());
        
        // 唤醒无限期wait
        Thread.sleep(100);
        synchronized (lock) {
            lock.notify(); // 唤醒线程
        }
        
        // 等待线程结束
        Thread.sleep(100);
        System.out.println("notify后状态: " + thread.getState());
        
        // 再次唤醒(如果还在wait)
        Thread.sleep(100);
        synchronized (lock) {
            lock.notify();
        }
        
        thread.join();
        System.out.println("最终状态: " + thread.getState());
    }
}

5. 特殊状态转换场景

5.1 线程中断(Interrupt)

public class ThreadInterruptExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("线程开始休眠10秒");
                Thread.sleep(10000);
                System.out.println("休眠正常结束");
            } catch (InterruptedException e) {
                System.out.println("线程被中断!");
                System.out.println("中断后状态: " + Thread.currentThread().getState());
                System.out.println("中断标志: " + Thread.currentThread().isInterrupted());
                
                // 恢复中断状态(最佳实践)
                Thread.currentThread().interrupt();
            }
        });
        
        thread.start();
        Thread.sleep(2000); // 等待2秒
        
        System.out.println("中断前状态: " + thread.getState()); // TIMED_WAITING
        System.out.println("中断标志: " + thread.isInterrupted()); // false
        
        thread.interrupt(); // 中断线程
        
        Thread.sleep(100);
        System.out.println("中断后状态: " + thread.getState()); // RUNNABLE
        System.out.println("中断标志: " + thread.isInterrupted()); // false(异常清除了标志)
        
        thread.join();
    }
}

5.2 join() 方法状态转换

public class ThreadJoinExample {
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            try {
                System.out.println("Thread1 开始执行");
                Thread.sleep(2000);
                System.out.println("Thread1 执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        Thread thread2 = new Thread(() -> {
            System.out.println("Thread2 等待 Thread1");
            try {
                thread1.join(); // Thread2进入WAITING状态,等待Thread1结束
                System.out.println("Thread1 已结束,Thread2 继续执行");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        
        thread1.start();
        thread2.start();
        
        // 监控状态
        try {
            Thread.sleep(500);
            System.out.println("Thread2状态 (等待join): " + thread2.getState()); // WAITING
            
            Thread.sleep(2000);
            System.out.println("Thread2状态 (join完成): " + thread2.getState()); // TERMINATED
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5.3 yield() 方法 - 不会改变状态

public class ThreadYieldExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("执行第 " + i + " 次");
                Thread.yield(); // 让出CPU,但状态保持RUNNABLE
            }
        });
        
        thread.start();
        
        // yield()不会改变线程状态,始终是RUNNABLE
        // 只是给调度器一个提示,可以切换到其他线程
    }
}

6. 实际应用中的状态监控

6.1 线程状态监控工具

public class ThreadMonitor {
    public static void monitorThread(Thread thread, String threadName) {
        new Thread(() -> {
            while (thread.isAlive()) {
                System.out.println(threadName + " 状态: " + thread.getState());
                try {
                    Thread.sleep(500); // 每500ms监控一次
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(threadName + " 已终止,最终状态: " + thread.getState());
        }).start();
    }
    
    public static void main(String[] args) throws InterruptedException {
        Thread worker = new Thread(() -> {
            System.out.println("工作线程开始");
            try {
                Thread.sleep(1000); // TIMED_WAITING
                
                synchronized (ThreadMonitor.class) {
                    ThreadMonitor.class.wait(); // WAITING
                }
                
                Thread.sleep(500); // TIMED_WAITING
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("工作线程结束");
        });
        
        // 启动监控
        monitorThread(worker, "Worker线程");
        
        // 启动工作线程
        worker.start();
        
        // 等待然后唤醒
        Thread.sleep(2000);
        synchronized (ThreadMonitor.class) {
            ThreadMonitor.class.notify();
        }
        
        worker.join();
    }
}

6.2 线程池中的线程状态

public class ThreadPoolStateExample {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        
        // 提交任务
        Future<?> future1 = executor.submit(() -> {
            System.out.println("任务1开始");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1结束");
        });
        
        Future<?> future2 = executor.submit(() -> {
            System.out.println("任务2开始");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
        });
        
        // 线程池中的线程状态
        Thread.sleep(1000);
        
        // 查看任务状态
        System.out.println("任务1是否完成: " + future1.isDone());
        System.out.println("任务2是否完成: " + future2.isDone());
        
        // 获取线程池中的工作线程(需要扩展ThreadPoolExecutor)
        executor.shutdown();
        executor.awaitTermination(10, TimeUnit.SECONDS);
    }
}

7. 状态相关API总结

7.1 Thread类相关方法

方法 说明 影响状态
start() 启动线程 NEW → RUNNABLE
run() 线程执行体 无状态变化
sleep(long) 睡眠指定时间 RUNNABLE → TIMED_WAITING
yield() 让出CPU时间片 保持RUNNABLE
join() 等待线程结束 RUNNABLE → WAITING
join(long) 限时等待线程结束 RUNNABLE → TIMED_WAITING
interrupt() 中断线程 可能从WAITING/TIMED_WAITING → RUNNABLE
isInterrupted() 检查中断标志 无状态变化
isAlive() 线程是否存活 NEW/TERMINATED返回false
getState() 获取线程状态 无状态变化

7.2 Object类相关方法

方法 说明 影响状态
wait() 无限期等待 RUNNABLE → WAITING
wait(long) 限时等待 RUNNABLE → TIMED_WAITING
notify() 唤醒一个等待线程 WAITING/TIMED_WAITING → RUNNABLE
notifyAll() 唤醒所有等待线程 WAITING/TIMED_WAITING → RUNNABLE

8. 常见问题与最佳实践

8.1 避免线程泄漏

public class ThreadLeakPrevention {
    public static void main(String[] args) {
        // 错误示例:线程永远WAITING,无法终止
        Thread leakThread = new Thread(() -> {
            synchronized (ThreadLeakPrevention.class) {
                try {
                    ThreadLeakPrevention.class.wait(); // 永远等待
                } catch (InterruptedException e) {
                    // 没有正确处理中断
                }
            }
        });
        leakThread.start();
        
        // 正确示例:使用超时或可中断的等待
        Thread safeThread = new Thread(() -> {
            synchronized (ThreadLeakPrevention.class) {
                try {
                    ThreadLeakPrevention.class.wait(30000); // 30秒超时
                } catch (InterruptedException e) {
                    System.out.println("线程被中断,正常退出");
                    Thread.currentThread().interrupt(); // 恢复中断状态
                    return; // 退出线程
                }
            }
        });
        safeThread.start();
    }
}

8.2 正确处理线程中断

public class ProperInterruptHandling {
    public static void main(String[] args) throws InterruptedException {
        Thread worker = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    System.out.println("工作中...");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("接收到中断信号");
                    // 两种选择:
                    // 1. 退出线程
                    Thread.currentThread().interrupt(); // 重新设置中断标志
                    break;
                    // 2. 继续执行(如果允许)
                }
            }
            System.out.println("线程结束");
        });
        
        worker.start();
        Thread.sleep(3500);
        worker.interrupt(); // 发送中断信号
        worker.join();
    }
}

8.3 状态诊断工具

public class ThreadDiagnosis {
    // 诊断线程死锁
    public static void diagnoseDeadlock() {
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] threadIds = threadMXBean.findDeadlockedThreads();
        
        if (threadIds != null) {
            ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadIds);
            System.out.println("发现死锁线程:");
            for (ThreadInfo info : threadInfos) {
                System.out.println("线程: " + info.getThreadName());
                System.out.println("状态: " + info.getThreadState());
                
                LockInfo[] lockedSyncs = info.getLockedSynchronizers();
                for (LockInfo lock : lockedSyncs) {
                    System.out.println("持有锁: " + lock);
                }
            }
        }
    }
    
    // 监控所有线程状态
    public static void monitorAllThreads() {
        Map<Thread.State, Integer> stateCount = new HashMap<>();
        
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for (Thread thread : threadSet) {
            Thread.State state = thread.getState();
            stateCount.put(state, stateCount.getOrDefault(state, 0) + 1);
        }
        
        System.out.println("=== 线程状态统计 ===");
        stateCount.forEach((state, count) -> {
            System.out.println(state + ": " + count + "个线程");
        });
    }
}

9. 总结

9.1 状态转换要点

  1. NEW → RUNNABLE: 只能通过 start() 转换

  2. RUNNABLE → BLOCKED: 只在 synchronized 锁竞争时发生

  3. RUNNABLE → WAITING/TIMED_WAITING: 调用特定方法

  4. WAITING/TIMED_WAITING → RUNNABLE: 被唤醒、超时或中断

  5. RUNNABLE → TERMINATED: 线程执行完毕

9.2 最佳实践

  1. 避免使用已废弃的方法:如 stop()suspend()resume()

  2. 合理使用中断机制:作为线程退出的优雅方式

  3. 注意锁的粒度:减少线程在BLOCKED状态的时间

  4. 使用超时机制:避免线程永远WAITING

  5. 监控线程状态:及时发现死锁、线程泄漏等问题

9.3 性能影响

  • RUNNABLE: CPU资源竞争

  • BLOCKED: 锁竞争,可能成为瓶颈

  • WAITING/TIMED_WAITING: 资源等待,可能影响响应时间

  • 上下文切换: 状态切换会消耗CPU资源

        理解线程生命周期对于编写高性能、稳定的多线程应用至关重要。合理管理线程状态可以避免死锁、提高资源利用率,并确保应用的正确性。

Logo

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

更多推荐