我们正在开发一个包含多个工作线程的Java应用程序。这些线程必须向我们的UI线程提供大量计算结果。结果的顺序无关紧要。
现在,所有线程只是将结果推送到同步堆栈 - 但这意味着每个线程必须等待其他线程才能传递结果。
是否存在支持同时插入的数据结构,每个插入在固定时间内完成?
谢谢,
马丁
答案 0 :(得分:10)
ConcurrentLinkedQueue专为高争用而设计。生产者在一端排队东西,消费者在另一端收集元素,所以一切都将按照添加的顺序进行处理。
ArrayBlockingQueue对于较低的争用更好,空间开销较低。
编辑:虽然这不是您要求的。 Simultaneuos插入?您可能希望为每个线程提供一个输出队列(例如,ArrayBlockingQueue
),然后让UI线程轮询单独的队列。但是,我认为您会发现以上两个Queue
实现中的一个已足够。
答案 1 :(得分:3)
现在,所有线程都只是推送 他们的结果是同步的 堆栈 - 但这意味着每一个 线程必须等待其他线程 在结果公布之前。
您是否有任何证据表明这实际上是一个问题?如果这些线程执行的计算甚至是最小的一点复杂(并且你没有数百万个线程),那么结果堆栈上的锁争用只是一个非问题,因为当任何给定的线程传递其结果时,所有其他人最有可能忙于计算。
答案 2 :(得分:1)
退后一步,评估性能是否是此处的关键设计考虑因素。不要想,知道:是否会对其进行分析?
如果没有,我会说更大的问题是设计的清晰度和可读性,而不是引入新代码来维护。碰巧的是,如果你正在使用Swing,那么有一个库可以完全你正在尝试做什么,称为SwingWorker
。
答案 3 :(得分:0)
查看java.util.concurrent.ConcurrentLinkedQueue
,java.util.concurrent.ConcurrentHashMap
或java.util.concurrent.ConcurrentSkipListSet
。他们可能会做你需要的。例如,ConcurrentSkipListSet
声称contains
,add
和remove
操作的预期平均 log(n)时间成本及其插入,删除和访问操作由多个线程安全地同时执行。“
答案 4 :(得分:0)
您可能想要查看的其他两种模式是
每个线程都有自己的集合,在轮询时它返回集合并创建一个新集合,因此集合只保存轮询之间的待处理项。线程需要保护其集合上的操作,但线程之间没有争用。这是阻塞(当UI线程从中获取更新时,每个线程都无法添加到其集合中),但可以减少争用(线程之间没有争用)。
每个线程都有自己的集合,并将结果附加到使用Lock.tryLock()保护的公共队列。如果线程无法获取锁定,则线程继续处理。这使得线程不太可能阻止等待共享队列。