生产者消费者的几种写法

本文介绍了四种实现生产者消费者模式的方法:1) 使用ArrayList和synchronized;2) 实现并发阻塞容器;3) 利用Lock和Condition;4) 使用BlockingQueue。文中详细探讨了wait/notify的使用细节,包括为何wait需配合while循环,为什么通常使用notifyAll而非notify,以及wait逻辑是否应置于main方法中。
摘要由CSDN通过智能技术生成

我自己根据理解写了4种,可能会存在问题,望指正!
问题描述:
开5个线程,作为生产者线程,每个线程往容器里放3个;
开5个消费者线程,每个线程从容器里get3次;
如果容器满了,生产者阻塞;
如果容器空了,消费者阻塞。

1.用一个普通的数据结构如ArrayList来实现。

利用synchronized和Object自带的wait()/notifyAll()方法实现。

public static void main(String[] args) {
		List<Integer> c=new ArrayList<Integer>(5);
		//producer
		for(int i=0;i<5;i++) {
			new Thread(()->{
				for(int j=0;j<3;j++) {
						while(true) {
						  synchronized(c) {
							  if(c.size()<5) {
										c.add(j);
										System.out.println(Thread.currentThread().getName()+"product "+j);
										c.notifyAll();
										break;
							  }else {
								  try {
									c.wait();
								  } catch (InterruptedException e) {
									e.printStackTrace();
								  }
							  }
						  }
						}		
				}
			},String.valueOf(i)).start();
		}
		for(int i=0;i<5;i++) {
			new Thread(()->{
				for(int j=0;j<3;j++) {
					while(true) {
						synchronized(c){
							if(c.size()>0) {
								int res=c.get(c.size()-1);
								c.remove(c.size()-1);
								System.out.println(Thread.currentThread().getName()+"comsume "+res);
								c.notifyAll();
								break;
							}else {
						        try {
								   c.wait();
							    } catch (InterruptedException e) {
								   e.printStackTrace();
							    }
							}
						}
					}	
				}
			},String.valueOf(-i)).start();
		}
	}

在写的过程中遇到了java.lang.IllegalMonitorStateException,也记录下,这个Exception是在调用object的wait和notify,notifyAll方法的时候可能会出现的异常。注意wait/notify的方法要放在同步代码块或同步方法里(synchronized里)。

2.实现一个并发阻塞的容器

如果每次都需要用外部程序来实现一个生产者消费者的case,有点低效,所以如果实现一个容器来完成这些工作会更好。

class Container<T>{
	private int cap;
	private List<T> list=null;
	public Container(int n) {
		cap=n;
		list=new ArrayList<>();
	}
	public synchronized boolean put(T n) {
		while(true) {
			if(list.size()<cap) {
				list.add(n);
				System.out.println(Thread.currentThread().getName()+"product "+n);
				notifyAll();
				break;
			}else {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		return true;
	}
	public synchronized boolean take() {
		while(true) {
			if(list.size()>0) {
				T res=list.get(list.size()-1);
				list.remove(list.size()-1);
				System.out.println(Thread.currentThread().getName()+"comsume "+res);
				notifyAll();
				break;
			}else {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}		
		return true;	
	}
	public int size() {
		return list.size();
	}
}

使用:

public static void main(String[] args) {
   
		Container<Integer> c=new Container<>(5);
		for(int i=0;i<5;i++) {
   
			new Thread(()->{
   
				for(int j=0;j<3;j++) {
   
					c.put(j);	
				}
			},String.valueOf(i)).start();
			new Thread(()->{
   
				for(int j=0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值