随机 java.util.NoSuchElementException 即使使用 wait()
Random java.util.NoSuchElementException even with using wait()
你能告诉我在什么情况下这段代码抛出 java.util.NoSuchElementException :
public class StackTest {
private LinkedList<Object> myList = new LinkedList<Object>();
public StackTest() {
Thread testStack = new Thread() {
@Override
public void run() {
while (true)
{
synchronized (myList)
{
try {
if (myList.size() == 0)
{
myList.wait();
}
Object elem = myList.removeLast();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
testStack.start();
}
public void enQueue(Object o)
{
synchronized(myList)
{
myList.addFirst(o);
myList.notifyAll();
}
}
}
我的循环总是在等待 enqueue 方法在添加元素后调用 notifyAll。但是有时,我在调用 myList.removeLast()
时会出现 java.util.NoSuchElementException
你应该坚持 the recommended pattern 并将你的条件放在 while
中以避免虚假唤醒。
synchronized (myList) {
try {
while (myList.size() == 0) {
myList.wait();
}
Object elem = myList.removeLast();
} catch (Exception e) {
e.printStackTrace();
}
}
问题是这行代码不再受同步保护:
Object elem = myList.removeLast();
调用列表上的 wait() 会释放锁的所有权,这样另一个线程就可以到达代码的通知部分。这也意味着多个线程可以等待 - 并立即得到通知。然后这些将同时尝试在您的列表上执行 removeLast() - 如果等待的线程多于列表中的元素,这将导致您描述的错误。
你能告诉我在什么情况下这段代码抛出 java.util.NoSuchElementException :
public class StackTest {
private LinkedList<Object> myList = new LinkedList<Object>();
public StackTest() {
Thread testStack = new Thread() {
@Override
public void run() {
while (true)
{
synchronized (myList)
{
try {
if (myList.size() == 0)
{
myList.wait();
}
Object elem = myList.removeLast();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
testStack.start();
}
public void enQueue(Object o)
{
synchronized(myList)
{
myList.addFirst(o);
myList.notifyAll();
}
}
}
我的循环总是在等待 enqueue 方法在添加元素后调用 notifyAll。但是有时,我在调用 myList.removeLast()
你应该坚持 the recommended pattern 并将你的条件放在 while
中以避免虚假唤醒。
synchronized (myList) {
try {
while (myList.size() == 0) {
myList.wait();
}
Object elem = myList.removeLast();
} catch (Exception e) {
e.printStackTrace();
}
}
问题是这行代码不再受同步保护:
Object elem = myList.removeLast();
调用列表上的 wait() 会释放锁的所有权,这样另一个线程就可以到达代码的通知部分。这也意味着多个线程可以等待 - 并立即得到通知。然后这些将同时尝试在您的列表上执行 removeLast() - 如果等待的线程多于列表中的元素,这将导致您描述的错误。