0

好的,我将通过举例来解释我的要求。

假设我在给定时尝试实现并行合并算法:

db是一个数组,其中db[i]是一个对象的 ArrayList。

j是它的大小。 Merger(db,cmp,i,j)是将db[ j ]合并 db[i] 的可运行对象。

cmp 是一个相关的比较器。

这是我首先完成的:

    ExecutorService e =  Executors.newFixedThreadPool(3);
    while (j>0) 
        for ( i=0;i<j;i++,j--) 
            e.execute(new Merger<E>(db,cmp,i,j));

但是随后开始了一些合并,而之前需要先完成的合并尚未完成。(更不用说正在运行的线程在合并完成之前完成了循环方式......)这让我的程序踢出了一个异常。

这是我不能做但想做的事,因此需要你的帮助:

    ExecutorService e =  Executors.newFixedThreadPool(3);
    while (j>0) {
        for ( i=0;i<j;i++,j--) 
            e.execute(new Merger<E>(db,cmp,i,j));
        wait for e to announce that all runnables have finished running;
    }

在我看来,这应该可行,如果您认为不行,请解释原因,但无论如何,我想知道它是如何完成的。

(基本上我可以实现我自己版本的 FixedThreadPool 以使其成为可能,但我宁愿不这样做)

4

3 回答 3

2

您可能正在寻找CountDownLatch

  • 确定您需要等待的线程数并CountDownLatch使用该数创建一个
  • 在构造它们时将锁存器传递给所有工作线程,并在countDown()它们完成后让它们调用。
  • 在将工作线程排入队列的循环之后,await()倒计时达到零。
于 2012-04-20T16:34:57.887 回答
1

您需要一个“startAndRendezvous”可运行文件,它发出合并并等待它们完成。通常,这是通过创建一组合并可运行任务集来完成的,该任务集带有指向 startAndRendezvous 中的 CountDownlatch 的回调,或者更灵活地,将 startAndRendezvous 作为构造函数参数传递给合并可运行对象。

最新的 Java 有一个 ForkJoinPool。看看这个类 - 它节省了一个明确的倒计时锁存器。

于 2012-04-19T19:12:02.300 回答
-1

一个应该工作的简单方法是在 Merger 中定义一个静态计数器:

public class Merger<E> ... {
  public static int runningCount=0;
  public Merger(...){
    runningCount++;
  }
  public void run(){
     ...
     runnningCount--;
  }
}

然后 :

ExecutorService e =  Executors.newFixedThreadPool(3);    
while (j>0) {
    for ( i=0;i<j;i++,j--) 
        e.execute(new Merger<E>(db,cmp,i,j));
    while(Merger.runningCount>0)
        Thread.sleep(10);
}
于 2012-04-20T11:41:17.937 回答