在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
什么是生产者消费者模式
生产者消费者模式通过一个容器(比如阻塞队列 BlockingQueue )来解决生产者和消费者的紧耦合问题。生产者和消费者之间不直接通信,而是通过阻塞队列来通信。生产者生产完数据后不用等待消费者处理,而是直接将生产的数据放入阻塞队列;消费者不从生产者那里要数据,而是直接从阻塞队列里取。阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
阻塞队列提供了可阻塞的 put 和 take 方法,以及支持定时的 offer 和 poll 方法。如果队列已经满了,那么 put 方法将阻塞直到有空间可用;如果队列为空,那么 take 方法将会阻塞直到阻塞队列里有元素可用。
为什么要用生产者消费者模式
- 生产者消费者模式可以使生产者类和消费者类解耦,这样能大大简化开发过程,因为它消除了生产者类和消费者类之间的代码依赖性。
- 生产者消费者模式可以解决生产消费能力不均衡的问题,从而提高整体处理数据的速度。假设不使用生产者消费者模式,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据;有了生产者消费者模式,生产者就可以不用等待消费者了,这样提高了生产者生产数据的效率。
使用阻塞队列实现生产者消费者模式
代码如下:
/**
* Created by lbd
*/
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
public class ProducerConsumerPattern {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new LinkedBlockingDeque<>(10);
for (int i = 0; i < 20; i++) {
new Thread(new Producer(blockingQueue), "Producer" + i).start();
}
for (int i = 0; i < 2; i++) {
new Thread(new Consumer(blockingQueue), "Consumer" + i).start();
}
}
}
class Producer implements Runnable {
private BlockingQueue<String> blockingQueue;
public Producer(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
try {
String product = "Produced by " + Thread.currentThread().getName();
blockingQueue.put(product);
System.out.println(Thread.currentThread().getName() + " produced a product");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<String> blockingQueue;
public Consumer(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
while (true) {
try {
String product = blockingQueue.take();
System.out.println(Thread.currentThread().getName() + " cunsumed product "+ product);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
输出:
Producer0 produced a product
Producer2 produced a product
Producer3 produced a product
Producer1 produced a product
Producer4 produced a product
Producer5 produced a product
Producer6 produced a product
Producer7 produced a product
Producer8 produced a product
Producer9 produced a product
Consumer0 cunsumed product Produced by Producer0
Producer11 produced a product
Producer12 produced a product
Producer10 produced a product
Consumer1 cunsumed product Produced by Producer1
Consumer0 cunsumed product Produced by Producer2
Producer13 produced a product
Consumer1 cunsumed product Produced by Producer3
Consumer1 cunsumed product Produced by Producer5
Producer15 produced a product
Consumer0 cunsumed product Produced by Producer4
Producer16 produced a product
Consumer1 cunsumed product Produced by Producer6
Producer14 produced a product
Producer18 produced a product
Consumer1 cunsumed product Produced by Producer8
Producer17 produced a product
Consumer0 cunsumed product Produced by Producer7
Producer19 produced a product
Consumer1 cunsumed product Produced by Producer9
Consumer0 cunsumed product Produced by Producer10
Consumer1 cunsumed product Produced by Producer11
Consumer0 cunsumed product Produced by Producer12
Consumer1 cunsumed product Produced by Producer13
Consumer0 cunsumed product Produced by Producer14
Consumer1 cunsumed product Produced by Producer15
Consumer0 cunsumed product Produced by Producer16
Consumer1 cunsumed product Produced by Producer17
Consumer0 cunsumed product Produced by Producer18
Consumer1 cunsumed product Produced by Producer19