这是我写的多线程队列的小片段,
synchronized void add(int i) {
if (count == size) {
System.out.println("******full***");
isQueueFull = true;
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("adding number: " + i);
val[end++] = i;
count++;
if (isQueueEmpty) {
isQueueEmpty = false;
this.notifyAll();
}
}
synchronized int remove() {
if (count == 0) {
isQueueEmpty = true;
System.out.println("******empty***");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int t = val[0];
for (int i = 0; i < end - 1; i++) {
val[i] = val[i + 1];
}
val[end - 1] = -1;
end--;
count--;
if (isQueueFull) {
isQueueFull = false;
this.notifyAll();
}
System.out.println("removing number: " + t);
return t;
}
假设我有四个线程添加到队列中,一个线程从队列中删除。有一次,假设数组已满,我在添加到队列的所有四个线程上调用wait。
现在当一个元素被删除时,我需要在所有休眠线程上调用notifyAll。(它给了我一个arrayOutofBound异常)我的问题是这样,在notifyAll的情况下线程流是什么。
由于add是synchronized方法,因此只能执行一个线程。但由于等待,我们现在有四个线程在其中睡觉。那么在notifyAll上,所有四个线程是否仍然在add方法中(尽管它是一个同步方法)并执行?或者它将按顺序逐个完成,所有线程都被锁定,直到一个线程完成。
我很难在eclipse中调试它。我通过在等待之后放置一个return语句来解决arrayOutOfBoundException,但我还是想了解notifyAll的情况下的流程?
答案 0 :(得分:2)
等待与睡觉有很大不同。 javadoc of wait()
解释了它:
线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。 线程然后等待,直到它可以重新获得监视器的所有权并继续执行。
(强调我的)
顺便说一下,它还包含一条你不尊重的强有力的规则:与一个参数版本一样,中断和虚假唤醒是可能的,此方法应始终在循环中使用:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
因此,当调用notifyAll()
时,4个线程竞争返回监视器。一旦前一个释放它,每个人都会收回它,然后继续执行。