说明

  • 在 Java中,wait() 方法是 Object 类的一个方法,通常用于多线程环境中的线程间通信

  • 它允许一个线程暂停执行,直到收到通知

  • wait() 方法应该在一个对象的同步上下文中调用,这意味着在调用 wait() 之前,线程必须已经获得了该对象的锁(通过使用 synchronized 关键字)

示例

下面是一个简单的使用 wait()notify() 的例子,展示了如何在两个线程之间进行同步操作。这个例子中有一个生产者线程(Producer)负责增加共享资源的数量,而消费者线程(Consumer)则减少这个数量。为了确保线程安全,我们使用了同步块,并且生产者在资源满的时候等待,消费者在资源为空的时候等待。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class WaitNotifyExample {
private int count = 0;
private final int max = 5;

public void produce() throws InterruptedException {
synchronized (this) { // 获取对象锁
while (count == max) {
System.out.println("仓库已满,等待空间...");
wait(); // 如果仓库满了,生产者等待
}
count++;
System.out.println("生产者生产了一个产品. 当前计数: " + count);
notifyAll(); // 唤醒其他等待的线程
}
}

public void consume() throws InterruptedException {
synchronized (this) { // 获取对象锁
while (count == 0) {
System.out.println("没有产品可消费, 等待产品...");
wait(); // 如果仓库空了,消费者等待
}
count--;
System.out.println("消费者消费了一个产品. 当前计数: " + count);
notifyAll(); // 唤醒其他等待的线程
}
}

public static void main(String[] args) {
WaitNotifyExample example = new WaitNotifyExample();

Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
example.produce();
Thread.sleep(1000); // 模拟耗时操作
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});

Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
example.consume();
Thread.sleep(1500); // 模拟耗时操作
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});

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

结论

  • 在这个例子中,wait() 方法让线程进入等待状态,直到另一个线程调用 notify()notifyAll() 方法

  • notifyAll() 会唤醒所有等待的线程,而 notify() 则只唤醒其中一个。注意,wait()notify*() 必须在同步上下文中调用,以避免发生并发修改异常。