生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。
实现方案1:synchronized关键字
synchronized介绍详见我的博客synchronized and CAS篇
package ProducerConsumerModel;
import java.util.LinkedList;
public class ProducerConsumerQueue {
static class Event{
}
private LinkedList<Event> queue = new LinkedList<Event>();
private final int max ;
private final int DEFAULT_MAX = 10;
public ProducerConsumerQueue() {
this.max = DEFAULT_MAX;
}
public ProducerConsumerQueue(int maxSize) {
this.max = maxSize;
}
/**
* 生产者生产方法
*/
public void offer(Event event) {
synchronized(queue) {
while(queue.size() >= max) {
try {
queue.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
queue.addLast(event);
queue.notifyAll();
}
}
/**
* 消费者消费方法
*/
public Event take() {
synchronized(queue) {
while(queue.isEmpty()) {
try {
queue.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
Event event = queue.removeFirst();
queue.notifyAll();
return event;
}
}
}
package ProducerConsumerModel;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.util.stream.Collectors.toList;
public class HandleQueue {
private static List<String> producerList = Arrays.asList("producer1","producer2","producer3");
private static List<String> consumerList = Arrays.asList("consumer1","consumer2","consumer3");
private static ProducerConsumerQueue queue = new ProducerConsumerQueue();
public static void main(String [] args) {
//创建三个生产者线程
List<Thread> producerthreads = producerList.stream().map(f->getProducerThread(f)).collect(toList());
//创建三个消费者线程
List<Thread> consumerthreads = consumerList.stream().map(f->getConsumerThread(f)).collect(toList());
//开启线程
producerthreads.forEach(Thread::start);
consumerthreads.forEach(Thread::start);
}
/**
* 创建生产者线程
*/
public static Thread getProducerThread(String name){
return new Thread(()->{
while(true) {
queue.offer(new ProducerConsumerQueue.Event());
System.out.println(Thread.currentThread().getName()+"生产了EVENT");
}
}
,name);
}
/**
* 创建消费者线程
*/
public static Thread getConsumerThread(String name){
return new Thread(()->{
while(true) {
queue.take();
System.out.println(Thread.currentThread().getName()+"消费了EVENT");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
,name);
}
}
实现方案2:实现Lock锁
Lock是一个接口,通过lock()方法和unlock()方法实现了对锁的显示控制,而synchronized则是对锁的隐性控制。
一个lock对象可以有多个Condition类,Condition类负责对lock对象进行wait,notify,notifyall操作。
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
public void offer(Event event) {
lock.lock();
while(queue.size() >= max) {
try {
notFull.await();
}catch(Exception e) {
e.printStackTrace();
}
}
queue.addLast(event);
notEmpty.signal();
lock.unlock();
}
public Event take() {
lock.lock();
while(queue.isEmpty()) {
try {
notEmpty.await();
}catch(Exception e) {
e.printStackTrace();
}
}
Event event = queue.removeFirst();
notFull.signal();
lock.unlock();
return event;
}
实现方案3:BlockingQueue
BlockingQueue是Java提供的实现了线程安全的阻塞队列
当队列满了的时候无法进行入队列操作,此时线程进入阻塞状态
当队列空了的时候无法进行出队列操作,此时线程进入阻塞状态
package ProducerConsumerModel2;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerQueue {
static class Event{
}
private final int DEFAULT_MAX = 10;
private final BlockingQueue<Event> blockingQueue;
public ProducerConsumerQueue() {
blockingQueue = new LinkedBlockingQueue<Event>(DEFAULT_MAX);
}
public ProducerConsumerQueue(int maxSize) {
blockingQueue = new LinkedBlockingQueue<Event>(maxSize);
}
public void offer(Event event) {
try {
blockingQueue.put(event);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public Event take() {
Event event = null;
try {
event = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return event;
}
}