У меня есть метод, который принимает массив запросов, и мне нужно запускать их против различных веб-API поисковой системы, таких как Google или Yahoo. Чтобы распараллелить процесс, для каждого запроса создается поток, который затем заканчивается join
ed, так как мое приложение может продолжить только после У меня есть результаты каждый запрос. Я в настоящее время есть что-то вдоль этих линий:Операция многопоточного поиска
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;
}
}
В последнее время я обнаружил, что есть новый API в Java для выполнения параллельных заданий. А именно, интерфейс 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
и т. Д. Мне бы хотелось услышать какие-либо советы по этому поводу.
Выглядит хорошо, не уверен, что я что-то изменил в вашем втором примере. В вашем первом примере я бы расширил Runnable и не Thread, но это просто nitpicking. –
+1, Это достаточно хорошо для меня. – akarnokd