Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java LinkedList与ConcurrentLinkedQueue_Java - Fatal编程技术网

Java LinkedList与ConcurrentLinkedQueue

Java LinkedList与ConcurrentLinkedQueue,java,Java,目前在多线程环境中,我们使用LinkedList保存数据。有时在日志中,当它轮询linkedlist时,我们不会得到任何TouchElementException。如果我们从linkedlist迁移到ConcurrentLinkedQueue实现,请帮助理解性能影响 谢谢, 萨钦 ConcurrentLinkedQueue[是]一个无边界、线程安全、FIFO排序的队列。它使用一个链接结构,类似于我们在第13.2.2节中看到的作为跳过列表基础的链接结构,以及在第13.1.1节中看到的哈希表溢出链接

目前在多线程环境中,我们使用LinkedList保存数据。有时在日志中,当它轮询linkedlist时,我们不会得到任何TouchElementException。如果我们从linkedlist迁移到ConcurrentLinkedQueue实现,请帮助理解性能影响

谢谢, 萨钦

ConcurrentLinkedQueue
[是]一个无边界、线程安全、FIFO排序的队列。它使用一个链接结构,类似于我们在第13.2.2节中看到的作为跳过列表基础的链接结构,以及在第13.1.1节中看到的哈希表溢出链接结构。我们注意到,链接结构的一个主要吸引人之处是,通过指针重新排列实现的插入和删除操作在恒定的时间内执行。这使得它们在队列实现中特别有用,在队列实现中,这些操作总是需要在结构末端的单元上进行,即不需要使用链接结构的慢速顺序搜索来定位的单元

ConcurrentLinkedQueue
使用一种基于CAS的无等待算法,该算法保证任何线程都可以完成其当前操作,而不管访问队列的其他线程的状态如何。它以固定时间执行队列插入和移除操作,但需要线性时间来执行
大小
。这是因为该算法依赖于线程之间的协作来进行插入和删除,它不跟踪队列大小,必须在需要时遍历队列来计算它

摘自,第14.2章


请注意,
ConcurrentLinkedQueue
没有实现
List
接口,因此仅当后者纯粹用作队列时,它就足以替代
LinkedList
。在这种情况下,
ConcurrentLinkedQueue
显然是更好的选择。除非经常查询其大小,否则不会有大的性能问题。但是作为免责声明,只有在您自己的具体环境和程序中对性能进行测量,您才能确定性能。

当您得到一个
NoTouchElementException
时,这可能是因为没有正确同步。 例如:您正在使用
it.hasNext()
检查列表中是否有元素,然后尝试使用
it.next()
获取该元素。如果在此期间删除了元素,则此操作可能会失败;如果使用同步版本的Collection API,也可能会失败

因此,移动到
ConcurrentLinkedQueue
并不能真正解决您的问题。您可能不会得到异常,但您必须做好准备,即使在检查之前它不是空的情况下,
null
也会返回。(这仍然是相同的错误,但实现不同。)只要代码中没有正确的同步,并且在相同的同步范围内检查空性和元素检索,则这是正确的

您很有可能会用
NoTouchElementException
换取新的
NullPointerException

这可能不是直接解决性能问题的答案,但在LinkedList中有
NoTouchElementException
作为转到
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) {
   ...
}


非常类似。这只是在不经意间被否决了一秒钟。在重新刷新
新答案时单击它,并立即更正。:)@致命的,那是另一个人,因为否决票仍然存在。@Peter我是否决票,现在又恢复了我的否决票。在我否决投票时,答案是一个quote块,没有指示quote的来源,也没有任何支持文本。你能建议一个实现
列表
接口的并发数据结构吗?在轮询列表之前有一个适当的检查。由于我们仍然没有得到任何TouchElementException,这意味着在检查其大小时列表中有数据,但在轮询时列表中没有数据。这可能是因为其他线程已经在同一时间轮询了它。移动到ConcurrentLinkedQueue将避免此类并发访问情况。@Sachin这正是我所说的。这正是迁移到ConcurrentLinkedQueue无法解决的问题!除非他将链表用作队列,因此不会对其进行迭代,只添加/删除第一个/最后一个元素。@Fatal您能详细解释一下吗?@Péter即使这样,他也必须准备好,当您在队列为空之前进行检查时,队列返回null。检查空白和检索必须在一个同步范围内。CLQ的优点是不会出现异常,并且可以避免检查空性,从而检查返回的null。
//queue is instance of CLQ
synchronized(queue) {
    if(!queue.isEmpty()) {
        ... queue.poll() //is not null
    }
}