随机 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() - 如果等待的线程多于列表中的元素,这将导致您描述的错误。