我有一种方法可以使用一系列的查询,我需要针对不同的搜索引擎Web运行它们,比如Google或Yahoo的。为了并行化这个过程,每个查询都会产生一个线程,然后在查询结束时进行join编辑,因为我的应用程序只能在得到每个查询的结果之后才能继续运行。我目前有这样的想法:
public abstract class class Query extends Thread {
private String query;
public abstract Result[] querySearchEngine();
@Override
public void run() {
Result[] results = querySearchEngine(query);
Querier.addResults(results);
}
}
public class GoogleQuery extends Query {
public Result querySearchEngine(String query) {
// access google rest API
}
}
public class Querier {
/* Every class that implements Query fills this array */
private static ArrayList<Result> aggregatedResults;
public static void addResults(Result[]) { // add to aggregatedResults }
public static Result[] queryAll(Query[] queries) {
/* for each thread, start it, to aggregate results */
for (Query query : queries) {
query.start();
}
for (Query query : queries) {
query.join();
}
return aggregatedResults;
}
}最近,我发现Java中有一个新的API来执行并发工作。即Callable接口、FutureTask和ExecutorService。我想知道这个新的API是否应该使用,以及它们是否比传统的Runnable和Thread更有效。
在研究了这个新API之后,我提出了以下代码(简化版本):
public abstract class Query implements Callable<Result[]> {
private final String query; // gets set in the constructor
public abstract Result[] querySearchEngine();
@Override
public Result[] call() {
return querySearchEngine(query);
}
}
public class Querier {
private ArrayList<Result> aggregatedResults;
public Result[] queryAll(Query[] queries) {
List<Future<Result[]>> futures = new ArrayList<Future<Result[]>>(queries.length);
final ExecutorService service = Executors.newFixedThreadPool(queries.length);
for (Query query : queries) {
futures.add(service.submit(query));
}
for (Future<Result[]> future : futures) {
aggregatedResults.add(future.get()); // get() is somewhat similar to join?
}
return aggregatedResults;
}
}我是这个并发API的新手,我想知道在上面的代码中是否有什么可以改进的,以及它是否比第一个选项(使用Thread)更好。有些类我没有研究过,比如FutureTask,等等。我也想听听关于这方面的任何建议。
发布于 2009-07-19 15:17:38
您的代码有几个问题。
因此,下面这样的内容应该有效:
public abstract class Query implements Callable<List<Result>> {
private final String query; // gets set in the constructor
public abstract List<Result> querySearchEngine();
@Override
public List<Result> call() {
return querySearchEngine(query);
}
}
public class Querier {
private static final ExecutorService executor = Executors.newCachedThreadPool();
public List<Result> queryAll(List<Query> queries) {
List<Future<List<Result>>> futures = executor.submitAll(queries);
List<Result> aggregatedResults = new ArrayList<Result>();
for (Future<List<Result>> future : futures) {
aggregatedResults.addAll(future.get()); // get() is somewhat similar to join?
}
return aggregatedResults;
}
}发布于 2009-07-19 15:10:58
作为进一步的改进,您可以考虑使用CompletionService --它解耦提交和检索的顺序,而将所有未来的结果放在一个队列中,从队列中获取结果的完成顺序。
发布于 2009-07-19 16:23:38
我可以建议你使用带有超时的Future.get()吗?
否则,只需要一个搜索引擎没有响应就能使一切停止(如果你的终端有网络问题的话,它甚至不需要成为搜索引擎问题)
https://stackoverflow.com/questions/1150073
复制相似问题