我试图找到一种方法,如何在具有一定最大线程限制的多个线程中加载多个网页,以便在完成一个新页面时加载。在下载页面后,还应该有加载内容的另一个后处理线程,以便整个过程被链接。
我想怎么做:
页面下载完成后,内容应转移到另一个任务队列进行后期处理
另一个线程池拥有尽可能多的线程,因为cpu具有内核(猜测每个内核只有一个线程用于后处理是最快的),此线程池对下载的页面执行后处理。
当页面的后处理完成后,线程应该通知它,以便队列中的另一个页面可以进行后处理
当所有页面都已下载(队列为空)时,可以关闭第一个线程池,当两个任务队列都为空(所有页面都已下载并进行后处理)时,可以关闭另一个线程池< / p>
我有类似的东西:
for (int j = 0; j < threads.length; j++) {
threads[j].start();
}
for (int j = 0; j < threads.length; j++) {
threads[j].join();
}
但是这样加载的所有页面都在同一个单独的线程中,我想限制线程数。更重要的是,我希望重用线程并使线程在一个任务完成时执行下一个任务。我可以用while循环来做到这一点,但这是我想要避免的,我不想要一个while循环来检查队列是否有更多任务以及线程是否空闲。是否可以使用某种回调,以便线程告诉已完成的池并返回数据。 我还希望下载任务能够将内容存储在数据结构中,并将其添加到后处理任务队列中。
我到目前为止找到的最佳资源是: Thread pools Callback
但我不知道是否有可能按照我想要的方式创建它。我一直在考虑函数指针。
答案 0 :(得分:3)
不要使用低级线程方法来执行此操作。拥有downloadExecutor
个线程池,并向此池提交DownloadTask
个实例(实现Runnable
或Callable
)。
在DownloadTask代码的末尾,将一个PostProcessPageTask实例(再次实现实现Runnable
或Callable
)提交给第二个postProcessExecutor
线程池。
您可以使用一个或两个CountDownLatch实例,每个任务在完成时都会减少,并让主线程在此(或这些)锁存器上等待,以了解何时必须关闭线程池。
有关详细信息,请参阅http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html和docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html。
答案 1 :(得分:1)
您可以使用Guava的ListenableFutures。
首先,您需要向ListenableExecutorService提交下载任务,然后通过Futures.transform使用后期处理器转换生成的期货。
ListenableExecutorService dlPool = MoreExecutors.listeningDecorator(firstPool);
ListenableExecutorService procPool = MoreExecutors.listeningDecorator(secondPool);
List<ListenableFuture<Result>> results = new ArrayList<...>();
for (String url : urls) {
// download task
ListenableFuture<String> html = dlPool.submit(...);
// post process
ListenableFuture<Result> result = Futures.transform(html,
new Function<String, Result>() {
... // post process
}, procPool);
results.add(result);
}
// blocks until all results are processed
List<Result> processed = Futures.allAsList(results).get();
firstPool.shutdownNow();
secondPool.shutdownNow();
答案 2 :(得分:-1)
不要试图手动编写这种类型的通用基础设施。
Java 5及更高版本附带了可爱的java.util.concurrent包
这应该是您制作多线程应用程序时首先要做的事情。
它有很多通用工具,比如线程池(执行Runnable或Callable对象),并会为你做很多狗工作。
互联网上有大量免费资源,或者如果您更喜欢书籍,Brian Goetz的“实践中的Java并发”被广泛认为是最好的之一。