生产者-消费者模式是一种经典的多线程编程模型,在 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) 手动实现线程同步
若需更灵活的控制,可使用 wait
和 notify
手动实现线程同步。
代码示例:
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 中常见于:
- 任务队列管理:如线程池中的任务调度。
- 数据流处理:如摄像头数据采集和图像处理分离。
- 异步通信: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. 注意事项
- 线程安全:始终确保对共享数据的访问使用同步机制。
- 资源管理:避免因线程阻塞导致资源泄漏。
- 队列容量控制:合理设置缓冲区大小,防止内存过载。
总结
生产者-消费者模式通过解耦生产和消费逻辑,提高了系统的灵活性和扩展性。在 Android 中,可以使用 BlockingQueue
简化实现,或通过手动同步实现更高的控制精度。结合具体应用场景选择合适的实现方式,可显著提高应用性能和稳定性。