java的wait和notify(java wait的作用)
# 简介在Java中,`wait()`、`notify()` 和 `notifyAll()` 是用于线程间通信的重要方法,它们属于 `Object` 类的一部分,通常与同步机制结合使用来实现线程间的协作。这些方法允许一个线程等待某个条件成立,而另一个线程在条件满足时通知等待的线程继续执行。本文将详细介绍这些方法的用法、工作机制以及注意事项。---# 一、基本概念与作用## 1.1 wait() 方法 -
定义
:`public final void wait()` -
作用
:使当前线程进入等待状态,并释放当前对象的锁。 -
特点
:调用 `wait()` 的线程会从运行状态变为等待(WAITING)状态,直到被其他线程通过 `notify()` 或 `notifyAll()` 唤醒。## 1.2 notify() 方法 -
定义
:`public final void notify()` -
作用
:唤醒一个正在等待该对象监视器的线程。 -
特点
:只会唤醒一个处于 WAITING 状态的线程,具体的线程选择是随机的。## 1.3 notifyAll() 方法 -
定义
:`public final void notifyAll()` -
作用
:唤醒所有正在等待该对象监视器的线程。 -
特点
:唤醒所有处于 WAITING 状态的线程,它们会在竞争锁后继续执行。---# 二、使用场景与示例代码## 2.1 线程协作的经典案例:生产者-消费者问题### 场景描述 生产者线程负责生成数据并存入缓冲区,消费者线程负责从缓冲区中取出数据进行处理。为了防止生产者过度生产或消费者过度消费,需要引入线程间的通信机制。### 示例代码 ```java class SharedResource {private int data;private boolean available = false;// 生产者方法public synchronized void produce(int value) throws InterruptedException {while (available) {wait(); // 如果资源已满,则等待}this.data = value;System.out.println("Produced: " + value);available = true; // 标记资源可用notify(); // 唤醒消费者}// 消费者方法public synchronized int consume() throws InterruptedException {while (!available) {wait(); // 如果资源不可用,则等待}int result = this.data;System.out.println("Consumed: " + result);available = false; // 标记资源不可用notify(); // 唤醒生产者return result;} }public class ProducerConsumerExample {public static void main(String[] args) {SharedResource resource = new SharedResource();Thread producerThread = new Thread(() -> {try {for (int i = 1; i <= 5; i++) {resource.produce(i);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread consumerThread = new Thread(() -> {try {for (int i = 1; i <= 5; i++) {resource.consume();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producerThread.start();consumerThread.start();} } ```### 运行结果 ``` Produced: 1 Consumed: 1 Produced: 2 Consumed: 2 Produced: 3 Consumed: 3 Produced: 4 Consumed: 4 Produced: 5 Consumed: 5 ```---# 三、注意事项## 3.1 必须在同步块中调用 - `wait()`、`notify()` 和 `notifyAll()` 必须在同步块(`synchronized` 块)中调用,否则会抛出 `IllegalMonitorStateException` 异常。 - 同步块确保了对共享资源的访问是安全的。## 3.2 避免虚假唤醒 - Java 并不能保证线程在调用 `wait()` 后一定会被唤醒,因此在退出等待前必须检查条件是否满足。 - 示例:```javasynchronized (this) {while (!condition) {wait();}}```## 3.3 notifyAll 的性能问题 - 虽然 `notifyAll()` 可以唤醒所有等待线程,但可能会导致不必要的竞争开销。如果明确知道只需要唤醒一个线程,优先使用 `notify()`。---# 四、总结`wait()`、`notify()` 和 `notifyAll()` 是 Java 中实现线程间通信的核心工具。它们通过让线程在特定条件下等待或唤醒,实现了高效的资源共享和任务调度。理解这些方法的工作原理及其适用场景,能够帮助开发者更高效地解决多线程编程中的复杂问题。同时,在实际开发中需要注意线程同步、条件判断等细节,避免潜在的问题。
简介在Java中,`wait()`、`notify()` 和 `notifyAll()` 是用于线程间通信的重要方法,它们属于 `Object` 类的一部分,通常与同步机制结合使用来实现线程间的协作。这些方法允许一个线程等待某个条件成立,而另一个线程在条件满足时通知等待的线程继续执行。本文将详细介绍这些方法的用法、工作机制以及注意事项。---
一、基本概念与作用
1.1 wait() 方法 - **定义**:`public final void wait()` - **作用**:使当前线程进入等待状态,并释放当前对象的锁。 - **特点**:调用 `wait()` 的线程会从运行状态变为等待(WAITING)状态,直到被其他线程通过 `notify()` 或 `notifyAll()` 唤醒。
1.2 notify() 方法 - **定义**:`public final void notify()` - **作用**:唤醒一个正在等待该对象监视器的线程。 - **特点**:只会唤醒一个处于 WAITING 状态的线程,具体的线程选择是随机的。
1.3 notifyAll() 方法 - **定义**:`public final void notifyAll()` - **作用**:唤醒所有正在等待该对象监视器的线程。 - **特点**:唤醒所有处于 WAITING 状态的线程,它们会在竞争锁后继续执行。---
二、使用场景与示例代码
2.1 线程协作的经典案例:生产者-消费者问题
场景描述 生产者线程负责生成数据并存入缓冲区,消费者线程负责从缓冲区中取出数据进行处理。为了防止生产者过度生产或消费者过度消费,需要引入线程间的通信机制。
示例代码 ```java class SharedResource {private int data;private boolean available = false;// 生产者方法public synchronized void produce(int value) throws InterruptedException {while (available) {wait(); // 如果资源已满,则等待}this.data = value;System.out.println("Produced: " + value);available = true; // 标记资源可用notify(); // 唤醒消费者}// 消费者方法public synchronized int consume() throws InterruptedException {while (!available) {wait(); // 如果资源不可用,则等待}int result = this.data;System.out.println("Consumed: " + result);available = false; // 标记资源不可用notify(); // 唤醒生产者return result;} }public class ProducerConsumerExample {public static void main(String[] args) {SharedResource resource = new SharedResource();Thread producerThread = new Thread(() -> {try {for (int i = 1; i <= 5; i++) {resource.produce(i);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread consumerThread = new Thread(() -> {try {for (int i = 1; i <= 5; i++) {resource.consume();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producerThread.start();consumerThread.start();} } ```
运行结果 ``` Produced: 1 Consumed: 1 Produced: 2 Consumed: 2 Produced: 3 Consumed: 3 Produced: 4 Consumed: 4 Produced: 5 Consumed: 5 ```---
三、注意事项
3.1 必须在同步块中调用 - `wait()`、`notify()` 和 `notifyAll()` 必须在同步块(`synchronized` 块)中调用,否则会抛出 `IllegalMonitorStateException` 异常。 - 同步块确保了对共享资源的访问是安全的。
3.2 避免虚假唤醒 - Java 并不能保证线程在调用 `wait()` 后一定会被唤醒,因此在退出等待前必须检查条件是否满足。 - 示例:```javasynchronized (this) {while (!condition) {wait();}}```
3.3 notifyAll 的性能问题 - 虽然 `notifyAll()` 可以唤醒所有等待线程,但可能会导致不必要的竞争开销。如果明确知道只需要唤醒一个线程,优先使用 `notify()`。---
四、总结`wait()`、`notify()` 和 `notifyAll()` 是 Java 中实现线程间通信的核心工具。它们通过让线程在特定条件下等待或唤醒,实现了高效的资源共享和任务调度。理解这些方法的工作原理及其适用场景,能够帮助开发者更高效地解决多线程编程中的复杂问题。同时,在实际开发中需要注意线程同步、条件判断等细节,避免潜在的问题。