在Java中,在多线程程序中保留前100项的最佳方法是什么?

时间:2014-10-16 22:02:40

标签: java multithreading sorting

我正在运行Java 8,我的应用程序是一个多线程搜索程序。它有数百个线程;每个都做一些计算并得到一个得分结果,所有线程将他们的结果放入一个向量。但是我不想保存所有的结果,因为它们有数百万,太多了,而且我只对分数[0 - 100]为80或更高的结果感兴趣,我只想收集结果的前100位,所以现在在我的应用程序中我有一个大小为100的向量。如果其中有少于100个项目,只需添加到它,当有100个项目时,执行以下操作:

myVector.set(99,result);
Collestions.sort(myVector);

因此,如果新项目得分较高,则最后一项始终得分最低并被替换。 我想知道这种方法是否最好,是否最快?还有其他更好的吗?

3 个答案:

答案 0 :(得分:4)

执行此操作的最快方法是使用heap(确保它是synchronized版本,如果它是多线程的)。堆允许您在日志时间中添加元素,还可以删除日志时间中的最小元素。

堆的Java实现是PriorityQueue,或者对于同步版本,PriorityBlockingQueue。在您的情况下,您需要PriorityBlockingQueue<Integer>

使用它的方法是有一个方法可以将一个可能的东西添加到堆中(即得分为80+的东西),然后

  1. 计算堆中有多少元素,如果它小于100,则添加此元素;否则:
  2. 查看堆中的最小元素(常量操作)并将其与您想要添加的内容进行比较;
  3. 如果这个得分高于当前最小值,则删除min(log n操作),然后在(log n operation)中添加这个新值。
  4. 在进程结束时,你的堆将包含100个顶部元素,你可以逐个从堆中读取(按顺序,从最小到最大,只需保持删除最小值)。

    (顺便说一下,这种堆与其他类型的堆无关,其中内存被分配给新对象。在计算机科学中有两个具有相同概念的关键概念有点不幸名。)

答案 1 :(得分:3)

答案 2 :(得分:3)

嗯,有两个缺点:

  1. 每次修改后调用Collections.sort效率都很低,因为它需要几百次比较。
  2. 任何时候只有一个线程可以与矢量交互。这对系统的可扩展性施加了限制。
  3. 这些缺点对您的应用程序是否真正重要是我们无法评估的,因为您没有给出任何性能目标。

    对于第一项,我切换到java.util.PriorityQueue,它支持有效删除最低元素。

    对于第二个问题,我给每个线程自己的PriorityQueue,并在收集完所有结果后合并队列。这样做的好处是线程在cpu时间密集阶段完全独立。