wait、notify 生产者消费者模式

aring_ 2016-10-12 05:04:42
建立了仓库,在生产者线程下,如果仓库已满,那么就wait(),释放仓库锁,否则就加入仓库中,调用notify()来提醒消费者线程可以消费了。在消费者线程下,如果仓库为空,那么就wait(),释放仓库锁,否则就从仓库消费中,调用notify()来提醒生产者线程可以生产了。在测试里,建立来两个生产者线程,三个消费者线程。那么现在的问题是:
1、跑了一段时间后,仓库溢出,报错。

2、发现在生产者线程下,只有仓库满的时候,才会释放仓库锁,那么不满的时候,线程一直拥有仓库锁,那么notify()其他线程也没有用啊,仓库锁也还没释放,怎么消费啊,所以感觉很怪。或许实现方式不对,求指教。

下面是实现代码:

public class Test {

public static void main(String[] args) {
Queue<Integer> store = new ArrayBlockingQueue<Integer>(10);
new Creator(store,10,"Creator1").start();
new Creator(store,10,"Creator2").start();
new Consumer(store,"Consumer1").start();
new Consumer(store,"Consumer2").start();
new Consumer(store,"Consumer3").start();
}

}


class Creator extends Thread{

private Queue<Integer> store;
private int sotreSize;

public Creator(Queue<Integer> store,int sotreSize,String name) {
super(name);
this.store = store;
this.sotreSize = sotreSize;
}


@Override
public void run() {
while(true){
try {
synchronized (store) {
if(store.size()==sotreSize){
System.out.println("仓库已满,等待消费...");
store.wait();
}
int e = (int) (Math.random()*10);
store.add(e);
System.out.println(Thread.currentThread().getName()+":"+e+"入库");
store.notify();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}

}

class Consumer extends Thread{

private Queue<Integer> store;

public Consumer(Queue<Integer> store,String name) {
super(name);
this.store = store;
}

@Override
public void run() {
while(true){
try {
synchronized (store) {
if(store.isEmpty()){
System.out.println("仓库为空,等待生产...");
store.wait();
}else{
Integer e = store.poll();
System.out.println(Thread.currentThread().getName()+":"+e+"出库");
}
store.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}



}




...全文
258 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
aring_ 2016-10-13
  • 打赏
  • 举报
回复
引用 4 楼 rickylin86 的回复:
在仓库增加一个库存之后调用sleep睡眠.注意是在同步代码块之后. 有可能是你的库存量设置为10太小。然后用是在while(true)循环中增加库存.所以一下子就填满了.是生产者线程睡眠能让消费者线程有时间执行.
我知道了,确实是我之前理解错了。同步块是放在while(ture)循环里,所以没循环一次都会主动释放锁,至于谁先抢到仓库,那就不一定了,但是当前释放锁的线程再次获得仓库的锁的几率会比较大,增加sleep睡眠,就使得当前释放锁的线程再次获得仓库的锁的几率几乎为0了,所以其他线程会有更大的机会获得仓库的锁。谢谢您的解答。
rickylin86 2016-10-12
  • 打赏
  • 举报
回复
在仓库增加一个库存之后调用sleep睡眠.注意是在同步代码块之后. 有可能是你的库存量设置为10太小。然后用是在while(true)循环中增加库存.所以一下子就填满了.是生产者线程睡眠能让消费者线程有时间执行.
aring_ 2016-10-12
  • 打赏
  • 举报
回复
引用 2 楼 rickylin86 的回复:
你试下把notify改成notifyAll看看结果
换成notifyAll是一样的啊
rickylin86 2016-10-12
  • 打赏
  • 举报
回复
你试下把notify改成notifyAll看看结果
aring_ 2016-10-12
  • 打赏
  • 举报
回复
问题1已经解决了。代码如下:

synchronized (store) {
        if(store.size()==sotreSize){
		System.out.println("仓库已满,等待消费...");
		store.wait();
	}else{
		int e = (int) (Math.random()*10);
		store.add(e);
		System.out.println(Thread.currentThread().getName()+":"+e+"入库");
	}
	store.notify();
       }

来讨论一下问题2.

50,549

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧