Operação de pesquisa multithread
Eu tenho um método que leva uma série de consultas, e eu preciso executá-los contra diferentes APIs do mecanismo de pesquisa da Web, como o Google ou o Yahoo. Para paralelizar o processo, um thread é gerado para cada consulta, que são entãojoin
no final, pois meu aplicativo só pode continuardepois de Eu tenho os resultados decada inquerir. Eu atualmente tenho algo ao longo destas linhas:
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;
}
}
Recentemente, descobri que há umaNovo API em Java para fazer trabalhos simultâneos. Ou seja, oCallable
interface,FutureTask
eExecutorService
. Eu queria saber se essa nova API é a que deve ser usada e, se forem mais eficientes que as tradicionais,Runnable
eThread
.
Depois de estudar esta nova API, eu criei o seguinte código (versão simplificada):
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;
}
}
Sou novo nessa API de concorrência e gostaria de saber se há algo que pode sermelhorado no código acima, e se for melhor que a primeira opção (usandoThread
). Existem algumas classes que eu não explorei, comoFutureTask
et cetera. Eu adoraria ouvir qualquer conselho sobre isso também.