如果我理解正确,您是在尝试将解决方案分解为多个部分并分别但同时解决,对吗?然后让您当前的线程等待这些任务?您想使用类似 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 中,通过 fork/join 池提供了更多支持。查看ForkJoinPool
及其踪迹,并使用 Google 查找许多其他教程之一。
您可以递归此概念以获得所需的树,只需让您创建的线程以完全相同的方式生成更多线程。
编辑:我的印象是你不会创建那么多线程,所以这更适合你的场景。该示例不会非常短,但它与您在另一个答案中的讨论相同,您可以等待工作,而不是线程。
首先,您Callable
的子作业需要 aInput
并返回 a 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 终止。
希望有帮助/有意义。