Bootstrap

在Java中如何使用wait()和notify()方法

在Java中,wait()notify()方法是用于线程间通信的重要同步机制。它们主要用于协调多个线程对共享资源的访问,确保线程安全。以下是对这两个方法的详细解释和使用场景说明:

1. wait()方法

定义

wait()方法使当前线程进入等待状态,直到其他线程调用此对象的notify()notifyAll()方法。当一个线程调用wait()时,它会释放该对象上的锁,并进入等待队列,直到被唤醒。

使用场景
  • 生产者-消费者模型:在生产者-消费者模型中,生产者线程生产数据后调用notify()通知消费者线程可以消费数据;消费者线程在没有数据可消费时调用wait()进入等待状态。
  • 任务调度:在某些任务调度系统中,某些任务可能需要等待特定条件满足后再继续执行,这时可以使用wait()让线程进入等待状态,直到条件满足时再被唤醒。

2. notify()方法

定义

notify()方法用于唤醒在此对象监视器上等待的单个线程。如果有多个线程在等待,则选择其中一个进行唤醒。被唤醒的线程将尝试重新获得对象的锁,并在成功获取锁后继续执行。

使用场景
  • 资源竞争:在多线程环境下,当某个线程完成了对共享资源的操作并释放了锁,它可以调用notify()来唤醒等待该资源的线程。
  • 事件驱动:在某些事件驱动的系统中,当某个事件发生时,可以调用notify()来通知等待该事件的线程进行处理。

3. 同步块内使用

定义

wait()notify()必须在同步块或同步方法内部使用。这是因为这些方法依赖于对象的内置锁(也称为监视器锁),而只有持有锁的线程才能调用这些方法。

使用场景
  • 保护临界区:在多线程编程中,临界区是一段需要互斥访问的代码。通过在同步块中使用wait()notify(),可以确保同一时间只有一个线程能够执行临界区内的代码。
  • 线程协作:在需要多个线程协作完成某项任务的场景下,可以使用wait()notify()来实现线程间的协调。

4. 释放锁

定义

调用wait()会释放锁,而调用notify()不会释放锁。这意味着在调用wait()之后,当前线程会释放它持有的锁,并进入等待状态;而在调用notify()之后,当前线程仍然持有锁,直到它退出同步块或同步方法。

使用场景
  • 避免死锁:通过在调用wait()时释放锁,可以避免死锁的发生。因为如果线程在持有锁的情况下进入等待状态,其他线程就无法获取锁,从而导致死锁。
  • 提高并发性:通过在调用notify()时不释放锁,可以提高系统的并发性。因为被唤醒的线程可以直接继续执行,而不需要重新竞争锁。

示例代码

以下是一个使用wait()notify()方法的简单示例,展示了生产者-消费者模型的基本实现:

public class ProducerConsumerExample {
    private static final Object lock = new Object();
    private static boolean condition = false;
    private static int item = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread producer = new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    while (condition) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    item++;
                    System.out.println("Produced: " + item);
                    condition = true;
                    lock.notify();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            synchronized (lock) {
                while (true) {
                    while (!condition) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("Consumed: " + item);
                    condition = false;
                    lock.notify();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

在这个示例中,生产者线程和消费者线程通过共享的lock对象进行同步。生产者线程在生产完一个项目后调用notify()唤醒消费者线程;消费者线程在消费完一个项目后调用notify()唤醒生产者线程。通过这种方式,实现了生产者和消费者之间的协调和通信。

;