目前在多线程环境中,我们使用 LinkedList 来保存数据。有时在日志中我们会在轮询链表时得到 NoSuchElementException。如果我们从链表转移到 ConcurrentLinkedQueue 实现,请帮助理解性能影响。

谢谢,
萨钦

最佳答案

当您获得 NoSuchElementException 时,这可能是因为没有正确同步。
例如:您正在使用 it.hasNext() 检查元素是否在列表中,然后尝试使用 it.next() 获取它。当元素在两者之间被删除时这可能会失败,并且当您使用 Collection API 的同步版本时也可能发生这种情况。

所以你的问题不能通过移动到 ConcurrentLinkedQueue 来真正解决。您可能没有收到异常,但是您必须准备好返回null,即使您在不为空之前进行了检查。 (这仍然是相同的错误,但实现有所不同。)只要您的代码中没有适当的同步检查空性和元素检索在相同的同步范围内,这就是正确的。

您很有可能在之后用 NoSuchElementException 换取新的 NullPointerException

这可能不是直接解决您关于性能的问题的答案,但是在 LinkedList 中使用 NoSuchElementException 作为转移到 ConcurrentLinkedQueue 的理由听起来有点奇怪。

编辑

一些损坏实现的伪代码:

//list is a LinkedList
if(!list.isEmpty()) {
    ... list.getFirst()
}

一些用于正确同步的伪代码:
//list is a LinkedList
synchronized(list) {
    if(!list.isEmpty()) {
        ... list.getFirst()
    }
}

一些用于“损坏”同步的代码(无法按预期工作)。
这可能是直接从LinkedList切换到CLQ的结果,希望自己摆脱同步。
//queue is instance of CLQ
if(!queue.isEmpty()) { // Does not really make sense, because ...
    ... queue.poll() //May return null! Good chance for NPE here!
}

一些正确的代码:
//queue is instance of CLQ
element = queue.poll();

if(element != null) {
   ...
}

或者
//queue is instance of CLQ
synchronized(queue) {
    if(!queue.isEmpty()) {
        ... queue.poll() //is not null
    }
}

关于java - LinkedList 与 ConcurrentLinkedQueue,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7316810/

10-10 15:38