返回

解锁生产者-消费者问题:使用 wait()/notify() 的多线程协作指南

Android

在计算机科学的广阔领域中,线程的概念至关重要,它允许并发执行任务,从而提高效率和响应能力。一个经典的线程同步问题是生产者-消费者问题,其中生产者线程生成数据,而消费者线程消耗该数据。理解和解决这个问题对于掌握多线程编程至关重要。

生产者-消费者问题

想象一个子弹工厂,生产者线程负责制造子弹,而消费者线程负责将子弹装填到枪支中。为了确保流畅的运作,生产者和消费者必须协调他们的行动。

生产者-消费者问题总结如下:

  1. 生产者线程: 产生数据(子弹)并将其存储在共享缓冲区中。
  2. 消费者线程: 从共享缓冲区中检索数据(子弹)并将其消耗掉。
  3. 协调: 生产者必须等待缓冲区有足够的空间来存放子弹,而消费者必须等待缓冲区中有子弹可供使用。

使用 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();
    }
}

步骤解释:

  1. 生产者线程: 如果缓冲区已满,则生产者调用 wait() 等待,直到有空间为止。然后,它将数据放入缓冲区并调用 notifyAll() 通知消费者线程。
  2. 消费者线程: 如果缓冲区为空,则消费者调用 wait() 等待,直到有数据为止。然后,它从缓冲区获取数据并调用 notifyAll() 通知生产者线程。
  3. 协调: 通过 wait()notify() 的交互,生产者和消费者线程协调他们的操作,确保缓冲区既不会溢出也不会饿死。

总结

使用 wait()notify() 实现的生产者-消费者问题是一个经典的多线程协作示例。它说明了线程如何同步操作,以确保共享资源的有效和无竞争的使用。通过利用这些方法,我们可以创建健壮且可扩展的多线程应用程序。