2016-11-29 2 views
0

Ich versuche, zwei Threads parallel aufzurufen. Jeder von ihnen muss eine Hash-Tabelle zurückgeben.Rufen Sie zwei Threads gleichzeitig mit return

Hier mein Code.

ExecutorService executor = Executors.newFixedThreadPool(2); 
Future<Map<Object, Map<String,Double>>> task1 = executor.submit(new GettingDataDaemon(request,0)); 
map = task1.get(); 
Future<Map<Object, Map<String,Double>>> task2 = executor.submit(new GettingDataDaemon(request,1)); 
map_compare = task2.get(); 
executor.shutdown(); 
while (!executor.isTerminated()) { 

} 
System.out.println("MAPS CREATED"); 

wo die GettingDataDaemon Klasse:

public class GettingDataDaemon implements Callable<Map<Object, Map<String,Double>>> { 

HttpServletRequest request; 
int index; 

public GettingDataDaemon(HttpServletRequest request, int index){ 
    this.request = request; 
    this.index = index; 
} 

@Override 
public Map<Object, Map<String,Double>> call() { 

    AbstractClass absClass = new AbstractClass(); 
    Map<Object, Map<String,Double>> map = absClass.getData(request, index); 
    System.out.println("Returning map "+(index+1)+"..."); 
    return map; 

} 

ich meinen Code getestet, aber der zweite Thread beginnt, nachdem der erste endete.

Was ist los?

Antwort

1

Als etablierte, Future.get() ist ein blockierender Aufruf, so sollte es sei denn, nicht aufgerufen werden, entweder das Ergebnis berechnet wurde, oder es ist die einzige Future links und Sie haben nichts anderes zu Warte nicht.

Um Ihre Daemons parallel auszuführen, ist es am einfachsten, nur einige Zeilen zu wechseln.

Future<Map<Object, Map<String,Double>>> task1 = executor.submit(new GettingDataDaemon(request,0)); 
Future<Map<Object, Map<String,Double>>> task2 = executor.submit(new GettingDataDaemon(request,1)); 
map = task1.get(); 
map_compare = task2.get(); 
executor.shutdown(); 

Sie wollen auch nicht, etwas so dumm wie while(!executor.isTerminated()) schreiben, da es beschäftigt Schleife und brennen Sie die CPU für absolut keinen Grund, auf. Verwenden Sie executor.awaitTermination(60, TimeUnit.SECONDS)) (wählen Sie natürlich das Timeout wie Sie möchten). Aber in diesem Fall, nachdem task2.get() zurückkehrt, müssen Sie nicht mehr auf die Beendigung warten.

2

Ihr Code wartet auf die erste Aufgabe aufgrund des Aufrufs von task1.get(). Sehen Sie sich die Dokumentation an:

V get(): Wartet, wenn die Berechnung abgeschlossen werden muss, und ruft dann das Ergebnis ab.

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()

+0

Gibt es eine Möglichkeit, diesen Ansatz zu verwenden? Könnte ich die beiden "Get" nach "Submit" nennen? – Fab

+1

Ja. Sie können nach dem Herunterfahren auf die futuretask-Instanz zugreifen – GurV

Verwandte Themen