0

假设我们有 n 个工人来做一些计算。计算可能需要一段时间,并且 n 次计算可能会并行运行。每个 Worker 都需要一些数据结构(不在 Worker 之间共享)来完成工作。

我想过在Master的一些初始化过程中设置每个Worker,并将所需的数据结构交给Worker的构造函数。

public class Master {

  public Master() {
     // initialize n Workers and "register" them "somewhere"
  }

  public boolean doCompute(int someInput) throws NoIdleWorkerException {
     // check if there is an idle Worker, otherwise throw NoIdleWorkerException
     // call the idle Worker, hand over someInput and wait for the result
     // synchronously return the result
  } 
}

一个 Worker 可以实现 Runnable,然后交给一个 Thread。一个 Worker 的实例可以被重用。

public class Worker implements Runnable {

  private SomeDataStructure ds;

  public Worker(SomeDataStructure ds) {
     this.ds = ds;
  }

  public void run() {
     // may call doCompute, but run() doesn't has a return type
  }

  public boolean doCompute(int someInput) {
     // do the computation an return
  } 
}

管理 Worker 实例的最佳方法是什么?我正在考虑使用 ThreadFactory ,它仅在 Worker 实例空闲时才返回 Thread,否则为 null。使用这种方法,我将不得不在某些数据结构中管理 Worker 实例。

另外,由于 Master.doCompute(int someInput) 有一个返回值,但它的计算是由一个线程完成的,因此是异步的,我可能不得不使用 Futures。有没有其他选择?

4

1 回答 1

1

假设您的 Master 必须对给定调用的所有工作人员的结果做某事,我会将每个工作人员实现为 Callable,并在其调用函数中实现要完成的工作。

然后,master 可以从你传入的任何内容生成它的 Callables 列表,并通过 invokeAll 方法将它们传递给 ThreadPoolExecutor(这意味着你可以控制实际用于这种并行处理的线程数)。

invokeAll 返回一个 Futures 列表,它要么已完成,要么已超时(如果您选择设置一个)。您可以检查他们是否已取消(超时)。

有关详细信息,请参阅http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/AbstractExecutorService.html#invokeAll(java.util.Collection)

于 2013-08-12T14:07:52.667 回答