返回
解锁生产者-消费者问题:使用 wait()/notify() 的多线程协作指南
Android
2023-10-22 11:37:51
在计算机科学的广阔领域中,线程的概念至关重要,它允许并发执行任务,从而提高效率和响应能力。一个经典的线程同步问题是生产者-消费者问题,其中生产者线程生成数据,而消费者线程消耗该数据。理解和解决这个问题对于掌握多线程编程至关重要。
生产者-消费者问题
想象一个子弹工厂,生产者线程负责制造子弹,而消费者线程负责将子弹装填到枪支中。为了确保流畅的运作,生产者和消费者必须协调他们的行动。
生产者-消费者问题总结如下:
- 生产者线程: 产生数据(子弹)并将其存储在共享缓冲区中。
- 消费者线程: 从共享缓冲区中检索数据(子弹)并将其消耗掉。
- 协调: 生产者必须等待缓冲区有足够的空间来存放子弹,而消费者必须等待缓冲区中有子弹可供使用。
使用 wait()/notify() 实现多线程协作
Java 中的 wait()
和 notify()
方法为线程同步提供了一种健壮且有效的机制。让我们使用它们来解决生产者-消费者问题。
// 共享缓冲区
class Buffer {
private int[] buffer;
private int head, tail;
public synchronized void put(int data) throws InterruptedException {
while (isFull()) {
wait();
}
buffer[tail] = data;
tail = (tail + 1) % buffer.length;
notifyAll();
}
public synchronized int get() throws InterruptedException {
while (isEmpty()) {
wait();
}
int data = buffer[head];
head = (head + 1) % buffer.length;
notifyAll();
return data;
}
private boolean isFull() {
return (tail + 1) % buffer.length == head;
}
private boolean isEmpty() {
return head == tail;
}
}
// 生产者线程
class Producer extends Thread {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
buffer.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 消费者线程
class Consumer extends Thread {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
int data = buffer.get();
System.out.println("Consumed: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// 主线程
public class Main {
public static void main(String[] args) {
Buffer buffer = new Buffer();
Producer producer = new Producer(buffer);
Consumer consumer = new Consumer(buffer);
producer.start();
consumer.start();
}
}
步骤解释:
- 生产者线程: 如果缓冲区已满,则生产者调用
wait()
等待,直到有空间为止。然后,它将数据放入缓冲区并调用notifyAll()
通知消费者线程。 - 消费者线程: 如果缓冲区为空,则消费者调用
wait()
等待,直到有数据为止。然后,它从缓冲区获取数据并调用notifyAll()
通知生产者线程。 - 协调: 通过
wait()
和notify()
的交互,生产者和消费者线程协调他们的操作,确保缓冲区既不会溢出也不会饿死。
总结
使用 wait()
和 notify()
实现的生产者-消费者问题是一个经典的多线程协作示例。它说明了线程如何同步操作,以确保共享资源的有效和无竞争的使用。通过利用这些方法,我们可以创建健壮且可扩展的多线程应用程序。