【问题标题】:NoSuchElementException on Queue队列上的 NoSuchElementException
【发布时间】:2014-08-23 00:37:25
【问题描述】:

我在使用 Java 中的 Queue 时遇到了一些问题。声明如下:

Queue<MotionEvent> touchQueue = new LinkedList<MotionEvent>();

我只在一个地方添加元素(但在回调中,很可能从线程调用):

@Override 
public boolean onTouchEvent(MotionEvent me) {
    touchQueue.add(me);
    return true;
}

我通过调用synchronized 函数来消耗主Thread 上的事件:

public synchronized void UpdateTouches() {
    while(!touchQueue.isEmpty()) {
        try {
            MotionEvent me = touchQueue.poll();
            ProcessTouchEvent(me);
        } catch (NoSuchElementException e) {
            return;
        }
    }
}

问题在于,有时民意调查会引发NoSuchElementException,之后所有后续民意调查都会引发Exception

有人知道可能是什么原因吗?或者有什么方法可以在不再次获取Exception 的情况下移除头部对象?

请注意,size() 在出现Exception 时返回 > 0,

谢谢, /C.

编辑:

这里是调用栈:

FATAL EXCEPTION: GLThread 302 java.util.NoSuchElementException
    at java.util.LinkedList.removeFirstImpl(LinkedList.java:689)
    at java.util.LinkedList.remove(LinkedList.java:899)
    at com.xxxxx.GG.GGActivity.UpdateTouches(GGActivity.java:718)
    at com.xxxxx.GG.GGView$Renderer.onDrawFrame(GGView.java:414)
    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
Force finishing activity

这是生成日志的函数的最新版本:

public synchronized void UpdateTouches()
{
    //System.out.println("Got touch event" + touchQueue.size());
    while(!touchQueue.isEmpty())
    {
        try {
            MotionEvent me = touchQueue.poll();
            ProcessTouchEvent(me);
        } catch (NoSuchElementException e)
        {
            touchQueue.remove();
            return;
        }

    }
}

【问题讨论】:

  • 从 LogCat 中显示该异常的调用堆栈。
  • 我将移除捕获并让它崩溃以进行崩溃转储,我会在我到达我的办公桌时返回。
  • 我添加了调用栈和最新版本的函数。
  • 我认为使用 touchQueue.clear(); 可以避免崩溃;而不是 touchQueue.remove();
  • @SuleaCosmin 如果队列中没有任何内容,调用 remove() 是错误的, 调用 clear() 毫无意义。

标签: java android multithreading exception nosuchelementexception


【解决方案1】:

当您已经知道队列为空时调用 remove() 没有任何意义。并在不抛出它的方法上捕获 NoSuchElementException,同上。只需删除所有代码即可。

但是您的代码不是线程安全的。调用 add() 的方法需要在队列上同步,调用 isEmpty() 和 poll() 的方法同上,应该等待队列为空。

或者使用 java.util.concurrent 队列。

【讨论】:

  • 我知道文档说明 poll 不会抛出 NoSuchElementException 但它是如何被抛出的,而 touchQueue.size() 返回正值并且 touchQueue.isEmpty() 返回 false 我只从 onDrawFrame 调用它(我没有任何其他机制可以从队列中删除项目)。我会尝试同步添加的块,看看是否有任何变化。
猜你喜欢
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多