生产者-消费者模式是一种经典的多线程编程模型,在 Android 开发中常用于任务队列的处理、数据流的解耦等场景。


1. 模式简介
  • 生产者:负责生成数据并放入缓冲区。
  • 消费者:从缓冲区取出数据并处理。
  • 缓冲区:用于存储生产者生成的数据,并在消费者消费后释放。

关键点:

  • 保证生产者和消费者线程安全。
  • 生产者在缓冲区满时等待,消费者在缓冲区空时等待。

2. 实现方式
(1) 使用 BlockingQueue

Java 提供了 BlockingQueue 类,天然支持线程安全,适合用于生产者-消费者模式。

代码示例:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerExample {
    private static final int QUEUE_CAPACITY = 5;
    private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);

    public static void main(String[] args) {
        // 启动生产者线程
        new Thread(() -> {
            try {
                for (int i = 1; i <= 10; i++) {
                    System.out.println("Producing: " + i);
                    queue.put(i); // 如果队列满,put 会阻塞
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Producer").start();

        // 启动消费者线程
        new Thread(() -> {
            try {
                while (true) {
                    Integer item = queue.take(); // 如果队列空,take 会阻塞
                    System.out.println("Consuming: " + item);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Consumer").start();
    }
}

运行效果:

  • 生产者线程生产数据放入队列。
  • 消费者线程从队列中取出数据并消费。
  • 队列满或空时,线程自动阻塞,避免资源浪费。

(2) 手动实现线程同步

若需更灵活的控制,可使用 waitnotify 手动实现线程同步。

代码示例:

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerManual {
    private static final int CAPACITY = 5;
    private final Queue<Integer> queue = new LinkedList<>();

    public static void main(String[] args) {
        ProducerConsumerManual pc = new ProducerConsumerManual();
        new Thread(pc::produce, "Producer").start();
        new Thread(pc::consume, "Consumer").start();
    }

    public void produce() {
        int value = 0;
        while (true) {
            synchronized (this) {
                while (queue.size() == CAPACITY) {
                    try {
                        wait(); // 队列满时等待
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
                queue.add(++value);
                System.out.println("Produced: " + value);
                notify(); // 唤醒消费者
            }
        }
    }

    public void consume() {
        while (true) {
            synchronized (this) {
                while (queue.isEmpty()) {
                    try {
                        wait(); // 队列空时等待
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
                int value = queue.poll();
                System.out.println("Consumed: " + value);
                notify(); // 唤醒生产者
            }
        }
    }
}

关键点:

  • 使用 wait() 使线程进入等待状态。
  • 使用 notify() 唤醒另一个线程。
  • 通过 synchronized 确保线程安全。

3. Android 场景应用

生产者-消费者模式在 Android 中常见于:

  1. 任务队列管理:如线程池中的任务调度。
  2. 数据流处理:如摄像头数据采集和图像处理分离。
  3. 异步通信:UI 主线程与后台工作线程之间的数据交互。

案例:后台任务队列

HandlerThread handlerThread = new HandlerThread("ProducerConsumerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());

Queue<String> taskQueue = new LinkedList<>();

// 生产者:添加任务到队列
handler.post(() -> {
    synchronized (taskQueue) {
        taskQueue.add("Task " + System.currentTimeMillis());
        taskQueue.notify();
    }
});

// 消费者:取任务并处理
new Thread(() -> {
    while (true) {
        synchronized (taskQueue) {
            while (taskQueue.isEmpty()) {
                try {
                    taskQueue.wait();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            String task = taskQueue.poll();
            System.out.println("Processing: " + task);
        }
    }
}).start();

4. 注意事项
  1. 线程安全:始终确保对共享数据的访问使用同步机制。
  2. 资源管理:避免因线程阻塞导致资源泄漏。
  3. 队列容量控制:合理设置缓冲区大小,防止内存过载。

总结

生产者-消费者模式通过解耦生产和消费逻辑,提高了系统的灵活性和扩展性。在 Android 中,可以使用 BlockingQueue 简化实现,或通过手动同步实现更高的控制精度。结合具体应用场景选择合适的实现方式,可显著提高应用性能和稳定性。