bf1,bf2是两个大小各为3的条件队列。3将要put进bf1,此时因为bf1已满而已调用wait()方法挂起线程,此时若对bf2()执行take()方法并调用notifyall()是否会唤醒wait()中的bf1?(对两个队列的操作存在于两个不同的线程中)
先上代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public abstract class BaseBoundedBuffer<V>{ private final V[] buf; private int tail; private int head; private int count; protected BaseBoundedBuffer(int capacity) { this.buf = (V[]) new Object[capacity]; } protected synchronized final void doPut(V v){ buf[tail]=v; if (++tail==buf.length){ tail=0; } ++count; } protected synchronized final V doTake(){ V v=buf[head]; buf[head]=null; if (++head == buf.length){ head=0; } --count; return v; } public synchronized final boolean isFull(){ return count==buf.length; } public synchronized final boolean isEmpty(){ return count==0; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class BoundedBuffer<V> extends BaseBoundedBuffer { private int id; protected BoundedBuffer(int capacity,int id) { super(capacity); this.id=id; } public synchronized void put(V v)throws InterruptedException{ //对条件队列执行增加元素的操作 while (isFull()){ System.out.println(id+"快睡了------put"); wait(); System.out.println(id+"醒了--------put"); } doPut(v); System.out.println(id+"put"+v); notifyAll(); } public synchronized V take() throws InterruptedException{ //对条件队列执行读取操作 while (isEmpty()){ System.out.println(id+"快睡了--------take"); wait(); System.out.println(id+"醒了----------take"); } V v= (V) doTake(); notifyAll(); return v; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class BufferTest { public static void main(String[] args) throws InterruptedException { BoundedBuffer bf =new BoundedBuffer(3,1); BoundedBuffer bf2=new BoundedBuffer(3,2); bf2.put(9999999); new Thread(){ public void run(){ for (int i=0;i<4;i++){ try { bf.put(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ public void run(){ try { System.out.println( bf2.take()); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } }
1 2 3 4 5 6 7 执行结果如下 2put9999999 1put0 1put1 1put2 1快睡了------put 9999999
在执行结果第五行的时候便是上图所描述的情况(3想要put进bf1,但是因为已经full,bf1进入wait()状态),第六行输出了9999999,也就说明bf2执行了take()操作,同时也执行了notifyAll()方法,然而对bf1没有产生任何影响。V v= (V) doTake();
notifyAll();
return v;
结果证明: 在使用条件队列时候,notifyAll()只会唤醒同一对象因执行wait()被挂起的线程