生产者消费者模型

本文介绍了生产者消费者模型,一种解决生产者与消费者之间强耦合问题的经典设计模式。通过阻塞队列作为中间件,平衡双方处理能力,降低耦合度。文中详细探讨了三种实现方式:使用synchronized关键字、Lock锁以及BlockingQueue。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生产者消费者模型

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。

实现方案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;			
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值