Ich habe eine Methode, die eine Reihe von Abfragen benötigt, und ich muss sie gegen verschiedene Suchmaschinen-Web-APIs ausführen, wie Google oder Yahoo. Um den Prozess parallel zu machen, wird für jede Abfrage ein Thread erzeugt, der dann am Ende join
ed wird, da meine Anwendung nur weiter nach ich habe die Ergebnisse alle abfragen kann. Im Moment habe ich etwas in dieser Richtung:Multithread-Suche
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;
}
}
Kürzlich habe ich festgestellt, dass es eine neue API in Java für die gleichzeitige Arbeit tun. Nämlich die Callable
Schnittstelle, FutureTask
und ExecutorService
. Ich habe mich gefragt, ob diese neue API die ist, die verwendet werden sollte, und wenn sie effizienter als die traditionellen sind, Runnable
und Thread
.
Nach dieser neuen API zu studieren, kam ich mit dem folgenden Code (vereinfachte Version) bis:
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;
}
}
Ich bin neu in dieser Gleichzeitigkeit API, und ich würde gerne wissen, ob es etwas gibt, das kann be verbesserte in dem obigen Code, und wenn es besser ist als die erste Option (mit Thread
). Es gibt einige Klassen, die ich nicht untersucht habe, wie FutureTask
und so weiter. Ich würde auch gerne einen Rat dazu hören.
Sieht gut aus, ich bin mir nicht sicher, ob ich in deinem zweiten Beispiel etwas ändern würde. In Ihrem ersten Beispiel würde ich Runnable und nicht Thread erweitern, aber das ist nur pingelig. –
+1, Es ist gut genug für mich. – akarnokd