J'ai une méthode qui prend un tableau de requêtes, et j'ai besoin de les exécuter sur différentes API Web de moteur de recherche, comme Google ou Yahoo. Afin de paralléliser le processus, un thread est généré pour chaque requête, qui est ensuite join
ed à la fin, puisque mon application ne peut que continuer après J'ai les résultats de toutes les requêtes. J'ai actuellement quelque chose le long de ces lignes:Opération de recherche multithread
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;
}
}
Récemment, j'ai trouvé qu'il ya une nouvelle API Java en pour faire des travaux simultanés. A savoir, l'interface Callable
, FutureTask
et ExecutorService
. Je me demandais si cette nouvelle API est celle qui devrait être utilisée, et si elles sont plus efficaces que les traditionnelles, Runnable
et Thread
.
Après avoir étudié cette nouvelle API, je suis venu avec le code suivant (version simplifiée):
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;
}
}
Je suis nouveau à cette API d'accès concurrentiel, et je voudrais savoir s'il y a quelque chose qui peut être amélioré dans le code ci-dessus, et si c'est mieux que la première option (en utilisant Thread
). Il y a des classes que je n'ai pas explorées, telles que FutureTask
, et cetera. J'aimerais avoir des conseils à ce sujet également.
Ça me va, pas sûr que je changerais quoi que ce soit dans ton second exemple. Dans votre premier exemple, j'allongerais Runnable et pas Thread, mais ce n'est que du nitpicking. –
+1, c'est assez bon pour moi. – akarnokd