问候Overflowers,
关于如何遍历这些树并最终以有限的线程获得最终结果的任何想法?
此致
答案 0 :(得分:3)
您想查看Topological Ordering有向无环图(DAG)。
如果图中的节点表示“作业”,则DAG的拓扑排序为您提供必须完成的顺序。维基百科页面具有到达订单的算法。
订单完成后,您的工作线程将开始从此订购中消耗“作业”(元素)。在开始作业之前,线程需要检查依赖作业是否已完成,但它们应该已完成,或者正在由另一个线程进行。
由于你有一个树形结构,你可能会遇到一些特殊情况:简单地将子节点放在第一位,然后将它们的父节点等放在另一个树的每个级别上。
此外,在问题上抛出“无限”的线程数会引起人们的注意......除非您的作业通常受I / O限制,否则(CPU数量+某些常量)线程似乎是合适的。 / p>
答案 1 :(得分:1)
类库提供了灵活的线程池实现以及一些有用的预定义配置。您可以通过调用Executors中的一个静态工厂方法来创建线程池。我认为对于你的情况应该使用以下方法:
newFixedThreadPool - 创建一个固定大小的线程池,在提交任务时创建线程,最大池大小,然后尝试保持池大小不变(如果线程因意外异常而死亡,则添加新线程)。
在创建线程池期间,您可以设置池大小,但是您可以根据需要向执行程序添加任意数量的线程(例如,每个节点的线程)。将不会执行的线程将排队。
如果您有一批计算要提交给执行人,并且您希望在结果可用时检索他们的结果,则可以使用完成服务。 CompletionService结合了Executor和BlockingQueue的功能。您可以向其执行可调用任务以执行,并使用队列,如方法take和poll来检索已完成的结果,打包为Futures,因为它们可用。 ExecutorCompletionService实现CompletionService,将计算委托给Executor。
以下是在Concurrency book中使用Java中的CompletionService的示例:
public class Renderer {
private final ExecutorService executor;
Renderer(ExecutorService executor) { this.executor = executor; }
void renderPage(CharSequence source) {
final List<ImageInfo> info = scanForImageInfo(source);
CompletionService<ImageData> completionService =
new ExecutorCompletionService<ImageData>(executor);
for (final ImageInfo imageInfo : info)
completionService.submit(new Callable<ImageData>() {
public ImageData call() {
return imageInfo.downloadImage();
}
});
renderText(source);
try {
for (int t = 0, n = info.size(); t < n; t++) {
Future<ImageData> f = completionService.take();
ImageData imageData = f.get();
renderImage(imageData);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
}
答案 2 :(得分:1)
对于CPU密集型任务,最佳线程数可能是您拥有的核心或逻辑线程数。这可能是您机器上的4,6或8。创建与可用物理线程数匹配的线程池的简单方法是。
ExecutorService pool = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors());
如果线程数多于核心数,则线程将不得不通过上下文切换增加开销并使其变慢。
答案 3 :(得分:1)
这看起来非常适合为Java 7开发的Fork / Join框架;它也适用于http://gee.cs.oswego.edu/dl/concurrency-interest/的Java 6(在jsr166y下)。您可以使用RecursiveTask
类来表示计算,并为数据结构中的子节点分配其他任务。 http://download.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html有一个简短的教程。