java并发线程-----阻塞队列的实现和思考

根据think in java 的描述,如果没有任务会阻塞,那么单处理器机器上使用并发就没有任何意义。这句话我觉得可以反着理解,那就是假如你对你的程序不考虑用并发来实现,那么你无须考虑任务的阻塞问题。
阻塞队列多半是解决对同一个(共享)资源进行操作的时候互相协作的问题。比如说有这样一个场景:某个工厂有生产工和搬运工两种角色,前者负责把生产好的产品放入仓库,
后者把仓库里面的产品搬出去卖。假如说仓库的产品数量为零,那么搬运工大可以睡上一觉,等生产工生产出产品,然后再搬。我们抽象出一个实现阻塞队列需要的元素,首先,仓库里面的产品是共享的资源,其次,生产工和搬运工需要互相协调这个资源的产生和消耗,他们应该是对应于程序中的两个线程,互不干扰又互相协调。
基于这个分析,我们就开始吧。
首先我们新建阻塞操作类blockoperator,代码如下:
       public class blockoperator {	private object notempty = new object();	private queue<object> linkedlist = new linkedlist<object>();	/**	 * 取物品	 * 	 * @return	 * @throws interruptedexception	 */ public object take() throws interruptedexception {	 synchronized (notempty) {	 string cureadname = thread.currentthread().getname();	 system.out.println("搬运工" + cureadname + "来到仓库");	 sleep(1000l);	 if (linkedlist.size() == 0) {	 // 假如仓库没东西了,那么就先不取物品,此时释放锁,被唤醒之前,需要先得到锁	system.out.println("搬运工" + cureadname + "发觉没有物品,只能等待生产");				notempty.wait();	}	object obj = linkedlist.poll();//返回并删除此元素	system.out.println("搬运工" + cureadname + "这时看到有了物品,搬出了:" + obj					+ "仓库还有物品数量:" + linkedlist.size());		return obj;}}// 生产物品public void offer(object object) throws interruptedexception {     synchronized (notempty) {	string cureadname = thread.currentthread().getname();	system.out.println("生产工" + cureadname + "来到仓库准备放物品");	sleep(3000l);	if (linkedlist.size() == 0) {	// 假如仓库没东西了,唤醒对象锁。分析:这个时候有可能没有等待锁,也可能有。	system.out.println("生产工" + cureadname+ "发现来到仓库的时候一件物品都没有,发觉搬运工在睡觉等他或者感觉搬运工在等他,于是喊醒了它");	notempty.notifyall(); 	/*	 * 注 假如仓库有东西,那么不用唤醒搬运工,因为有物品的时候,搬运工不会等待。	 * 分析:有的人肯定会觉得,有没有这种可能:当linkedlist.size=0的时候,notempty就wait了,然后在本同步块中,	 * 发现linkedlist.size!=0,那么notempty就不会去唤醒了。其实这完全没有可能,因为size!=0只有在完成了	 * linkedlist.add之后才有可能,而在add之前,必然会判断size=0的情况           */	}	system.out.println("生产工" + cureadname + "把物品" + object					+ "放到了仓库");	linkedlist.add(object);	}} private void sleep(long time) {	try {		thread.sleep(time);// 模拟时间消耗		} catch (interruptedexception e) {			e.printstacktrace();		}	}     


[color=red]注:本类中,首先创建了一个notempty做锁的对象,取物品的时候当产品为0时,notempty等待,此时会让位与另一个线程(生产)得到此对象锁,并且唤醒notempty上所有的等待锁。在生产完成之后,由于刚才等待的线程已经被唤醒,那么这个搬运工会移除此产品。下面会有我本机运行的效果,对照看一下会一目了然[/color]

然后创建生产工线程类createproduce,代码如下:
/** * 模拟工厂生产产品 *  * @author administrator *  */public class createproduce implements runnable {	private blockoperator bq;	public createproduce(blockoperator bq){		this.bq=bq;	}		@override	public void run() {		//生产n个产品		for(int i=0;i<5;i++){			object obj="a"+i;			try {				bq.offer(obj);			} catch (interruptedexception e) {				e.printstacktrace();			}		}			}}

此类比较简单,创建5个商品。

继续创建搬运工线程类,代码如下
/** * 模拟工厂搬运产品 * @author administrator * */public class getproduce implements runnable {	private blockoperator bq;	public getproduce(blockoperator bq){		this.bq=bq;	}	@override	public void run() {		 try {			 //搬运工是有多少搬多少			 while(true){				 object obj=bq.take();			 }					} catch (interruptedexception e) {			e.printstacktrace();		}	}}



最后新建一个测试类 如下:
public class testmain {	public static void main(string[] args) {		blockoperator bq = new blockoperator();		thread createthread = new thread(new createproduce(bq),"creater");		thread getthread = new thread(new getproduce(bq),"getter");		createthread.start();		getthread.start();					}}


在我本地运行的结果如下:
[img]http://dl.iteye.com/upload/attachment/509780/96c204ca-6016-3c22-9a54-6293fb590a5c.jpg[/img]

当我准备想在blockoperator里面加一个判断产品最大数量的锁对象,比如themaxobject,后来在take和offer里面分别加上限制,但是免不了会嵌套synchronized,那么这样会产生死锁。死锁大多是嵌套synchronized产生的。快下班了,写的快,刚才那个问题没太细想,高手们可以帮助出解决方案。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值