跳转到内容

Java线程状态

来自代码酷

Java线程状态是理解多线程编程的核心概念之一。在Java中,线程在其生命周期中会经历多种状态,这些状态反映了线程在不同时间点的行为特征。本教程将详细介绍Java线程的所有状态、状态转换条件以及实际应用示例。

线程状态概述[编辑 | 编辑源代码]

在Java中,线程的状态由

java.lang.Thread.State

枚举定义,包含以下6种状态:

  • NEW
    
    (新建)
  • RUNNABLE
    
    (可运行)
  • BLOCKED
    
    (阻塞)
  • WAITING
    
    (等待)
  • TIMED_WAITING
    
    (计时等待)
  • TERMINATED
    
    (终止)

通过

Thread.getState()

方法可以获取当前线程的状态。

状态转换图[编辑 | 编辑源代码]

以下Mermaid图展示了线程状态的完整转换流程:

stateDiagram-v2 [*] --> NEW NEW --> RUNNABLE: start() RUNNABLE --> BLOCKED: 等待监视器锁 RUNNABLE --> WAITING: wait()/join() RUNNABLE --> TIMED_WAITING: sleep(n)/wait(n)/join(n) BLOCKED --> RUNNABLE: 获取锁 WAITING --> RUNNABLE: notify()/notifyAll() TIMED_WAITING --> RUNNABLE: 超时或唤醒 RUNNABLE --> TERMINATED: run()结束

详细状态说明[编辑 | 编辑源代码]

1. NEW(新建)[编辑 | 编辑源代码]

线程被创建但尚未启动时的状态。

  
Thread thread = new Thread(() -> System.out.println("Running"));  
System.out.println(thread.getState()); // 输出: NEW

2. RUNNABLE(可运行)[编辑 | 编辑源代码]

线程调用

start()

后进入此状态,包括:

  • 正在CPU上执行
  • 就绪状态(等待CPU调度)
  
thread.start();  
System.out.println(thread.getState()); // 可能输出: RUNNABLE

3. BLOCKED(阻塞)[编辑 | 编辑源代码]

线程因等待获取同步锁而阻塞。例如:

  
public class BlockedExample {  
    public static void main(String[] args) throws InterruptedException {  
        Object lock = new Object();  
        Thread t1 = new Thread(() -> {  
            synchronized (lock) {  
                while (true); // 无限持有锁  
            }  
        });  
        Thread t2 = new Thread(() -> {  
            synchronized (lock) {  
                System.out.println("Lock acquired");  
            }  
        });  
        t1.start();  
        Thread.sleep(100); // 确保t1先获取锁  
        t2.start();  
        Thread.sleep(100);  
        System.out.println(t2.getState()); // 输出: BLOCKED  
    }  
}

4. WAITING(无限等待)[编辑 | 编辑源代码]

通过以下方法进入此状态:

  • Object.wait()
    
    (未指定超时)
  • Thread.join()
    
    (未指定超时)
  
public class WaitingExample {  
    public static void main(String[] args) throws InterruptedException {  
        Thread mainThread = Thread.currentThread();  
        Thread t = new Thread(() -> {  
            try {  
                Thread.sleep(2000);  
                System.out.println(mainThread.getState()); // 输出: WAITING  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        });  
        t.start();  
        t.join(); // 主线程等待t结束  
    }  
}

5. TIMED_WAITING(计时等待)[编辑 | 编辑源代码]

WAITING

类似,但带有超时参数:

  • Thread.sleep(long)
    
  • Object.wait(long)
    
  • Thread.join(long)
    
  
Thread.sleep(1000);  
System.out.println(Thread.currentThread().getState());  
// 在sleep期间输出: TIMED_WAITING

6. TERMINATED(终止)[编辑 | 编辑源代码]

线程执行完

run()

方法或抛出未捕获异常后的状态。

  
Thread t = new Thread(() -> System.out.println("Done"));  
t.start();  
Thread.sleep(100);  
System.out.println(t.getState()); // 输出: TERMINATED

实际应用案例[编辑 | 编辑源代码]

线程池监控[编辑 | 编辑源代码]

通过检查线程状态实现线程池健康监测:

  
ExecutorService executor = Executors.newFixedThreadPool(3);  
executor.submit(() -> {  
    try {  
        Thread.sleep(5000);  
    } catch (InterruptedException e) {  
        Thread.currentThread().interrupt();  
    }  
});  

// 监控线程状态  
new Thread(() -> {  
    while (true) {  
        executor.execute(() -> {  
            System.out.println("Current state: " +   
                Thread.currentThread().getState());  
        });  
        try { Thread.sleep(1000); } catch (InterruptedException e) {}  
    }  
}).start();

常见问题[编辑 | 编辑源代码]

  • Q: WAITING和BLOCKED的区别?

A:

BLOCKED

是等待获取锁,

WAITING

是主动放弃锁并等待唤醒。

  • Q: 如何避免线程永久阻塞?

A: 使用

wait(long)

替代无参

wait()

,或设计超时机制。

总结[编辑 | 编辑源代码]

理解线程状态对于调试多线程程序至关重要。关键要点:

  1. 状态转换由JVM内部机制和显式API调用控制
  2. RUNNABLE
    
    实际包含操作系统层面的"运行"和"就绪"两种子状态
  3. 合理使用
    TIMED_WAITING
    
    可提高系统健壮性

通过

jstack

工具或Java Mission Control可以实时观察线程状态,这是分析死锁或性能问题的标准方法。