条件队列的唤醒机制探究

这里写图片描述
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()被挂起的线程

文章目录
  1. 1. 先上代码
|