私の理解が正しければ、解決策をいくつかの部分に分割し、それらを別々に解決しようとしていますが、同時に解決しようとしていますよね? 次に、現在のスレッドにそれらのタスクを待機させますか? fork/join パターンのようなものを使用したい。
List<CustomThread> threads = new ArrayList<CustomThread>();
for (Something something : somethings) {
threads.add(new CustomThread(something));
}
for (CustomThread thread : threads) {
thread.start();
}
for (CustomThread thread : threads) {
thread.join(); // Blocks until thread is complete
}
List<Result> results = new ArrayList<Result>();
for (CustomThread thread : threads) {
results.add(thread.getResult());
}
// do something with results.
Java 7 では、フォーク/ジョイン プールを介したサポートがさらに強化されています。ForkJoinPool
とそのトレイルを参照し、Google を使用して他の多くのチュートリアルの 1 つを見つけてください。
この概念を再帰して、必要なツリーを取得できます。作成したスレッドにまったく同じ方法でさらにスレッドを生成させるだけです。
編集:それほど多くのスレッドを作成しないという印象を受けていたので、これはシナリオに適しています。例はひどく短くはありませんが、スレッドではなくジョブを待つことができるという、他の回答での議論と同じ流れに沿っています。
まず、 を受け取ってを返すCallable
サブジョブ用のが必要です。Input
Result
public class SubJob implements Callable<Result> {
private final Input input;
public MyCallable(Input input) {
this.input = input;
}
public Result call() {
// Actually process input here and return a result
return JobWorker.processInput(input);
}
}
それを使用するにExecutorService
は、固定サイズのスレッド プールを使用して を作成します。これにより、同時に実行するジョブの数が制限されるため、誤ってシステムをスレッド爆撃することはありません。あなたの主な仕事は次のとおりです。
public class MainJob extends Thread {
// Adjust the pool to the appropriate number of concurrent
// threads you want running at the same time
private static final ExecutorService pool = Executors.newFixedThreadPool(30);
private final List<Input> inputs;
public MainJob(List<Input> inputs) {
super("MainJob")
this.inputs = new ArrayList<Input>(inputs);
}
public void run() {
CompletionService<Result> compService = new ExecutorCompletionService(pool);
List<Result> results = new ArrayList<Result>();
int submittedJobs = inputs.size();
for (Input input : inputs) {
// Starts the job when a thread is available
compService.submit(new SubJob(input));
}
for (int i = 0; i < submittedJobs; i++) {
// Blocks until a job is completed
results.add(compService.take())
}
// Do something with results
}
}
これにより、ジョブを実行するたびに一連の新しいスレッドを生成する代わりに、スレッドを再利用できます。完了サービスは、ジョブが完了するのを待っている間にブロックを行います。また、results
リストは完成順となりますのでご注意ください。
Executors.newCachedThreadPool
を使用して、上限のないプールを作成することもできます( の使用と同様Integer.MAX_VALUE
)。スレッドが使用可能な場合はスレッドを再利用し、プール内のすべてのスレッドがジョブを実行している場合は新しいスレッドを作成します。これは、後でデッドロックが発生し始めた場合に望ましい場合があります (固定スレッド プールで待機しているジョブが多すぎて、サブジョブを実行および完了できないため)。これにより、作成/破棄するスレッドの数が少なくとも制限されます。
最後にExecutorService
、おそらくシャットダウン フックを介して手動でシャットダウンする必要があります。そうしないと、含まれるスレッドによって JVM を終了できなくなります。
それが役立つ/意味があることを願っています。