理解 Java 线程的 Blocked 和 Wait 状态
在并发编程中,线程是执行程序的基本单位。Java 提供了丰富的线程管理工具来处理并发问题。当我们在使用多线程的过程中,常常会遇到线程处于不同状态的情况。在这一篇文章中,我们将重点讨论 Java 线程的 Blocked 和 Wait 状态,并且通过代码示例来加深理解。
线程状态概述
Java 线程有几种主要状态:
- New: 线程被创建,但还未调用
start()
方法。 - Runnable: 线程可以运行,或者正在运行。
- Blocked: 线程由于正在等待某个对象的监视器锁而被阻塞。
- Waiting: 线程在等待其他线程的特定操作(如
join()
或wait()
),并不占用 CPU 资源。 - Timed Waiting: 线程等待某个操作的结束,但有一个时间限制(如
sleep()
、wait(timeout)
)。 - Terminated: 线程执行完毕,或因异常导致终止。
Blocked 状态
Blocked 状态的产生
当两个或多个线程竞争同一个监视器锁时,如果一个线程持有锁,其他线程就会被阻塞,直至持锁线程释放该锁。此状态下,线程无法继续执行,直到获得锁。
Blocked 示例代码
以下示例演示了线程如何因竞争锁而进入 Blocked 状态:
public class BlockedExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1: Holding lock...");
try {
// 线程持有锁并阻塞一段时间
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
// thread2 尝试获取相同的锁
synchronized (lock) {
System.out.println("Thread 2: Acquired lock!");
}
});
thread1.start();
thread2.start();
}
}
在这个示例中,Thread 1
持有 lock
的监视器锁,Thread 2
则必须等待,直到 Thread 1
释放锁。在此期间,Thread 2
将处于 Blocked 状态。
Wait 状态
Wait 状态的产生
当线程调用 Object.wait()
方法时,它会放弃锁并进入 Wait 状态。这意味着它将被挂起,直到其他线程调用 notify()
或 notifyAll()
方法来唤醒它。
Wait 示例代码
以下示例演示了线程如何进入 Wait 状态:
public class WaitExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1: Holding lock and waiting...");
try {
lock.wait(); // 进入待等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Resumed!");
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2: Holding lock and notifying...");
lock.notify(); // 唤醒等待的线程
}
});
thread1.start();
// 确保 thread1 先获取锁并进入等待状态
try {
Thread.sleep(100); // 确保 thread1 能首先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.start();
}
}
在这个示例中,Thread 1
在获取 lock
的监视器锁后,调用了 wait()
方法,此时它进入 Wait 状态,直到 Thread 2
调用 notify()
进行唤醒。
流程图
以下是描述线程状态流转的流程图:
flowchart TD
A[New] -->|start()| B[Runnable]
B -->|run()| C[Blocked]
C -->|lock released| B
B -->|wait()| D[Waiting]
D -->|notify()| B
B -->|notifyAll()| B
B -->|finished| E[Terminated]
线程调度的甘特图
以下是一个简单的甘特图,用以描述线程调度:
gantt
title Thread Scheduling Example
dateFormat YYYY-MM-DD
section Thread1
Blocked :a1, 2023-10-01, 2d
Waiting :after a1 , 2d
section Thread2
Running :a2, 2023-10-02, 2d
结论
在 Java 的多线程编程中,理解线程的 Blocked 状态与 Wait 状态十分重要。它们涉及至关重要的线程同步和资源竞争问题。合理地管理线程状态,不仅可以提升程序效率,还可以避免潜在的死锁和资源浪费。通过示例代码和流程图,我们希望你能更好地理解这些概念。希望这篇文章能为你的 Java 多线程编程之旅带来帮助!