2013-06-22 6 views
16

Ich versuche, eine Feder @ Async-Aufgabe zu implementieren, die einen Rückgabetyp der Zukunft, hat, aber ich kann nicht wirklich herausfinden, wie es richtig geht.Frühling 3.2 @ Async-Aufgabe mit Rückgabetyp der Zukunft

  1. Was kann ich dabei gewinnen? werde ich jetzt eine Kontrolle über meine Aufgabe haben, damit ich sie stoppen und ausführen kann?
  2. Gibt es eine Referenzimplementierung, wie ich das machen kann? springource bietet keine an.

EDIT

Von Frühling Quelle und Feder refrence Handbuch:

Auch Methoden, die einen Wert zurückgeben asynchron aufgerufen werden kann. Diese Methoden benötigen jedoch , um einen Future typisierten Rückgabewert zu haben. Dies bietet weiterhin den Vorteil einer asynchronen Ausführung, so dass der Aufrufer andere Aufgaben ausführen kann, bevor er get() für diesen Future aufruft.

und es gibt ein Beispiel, wie so:

@Async 
Future<String> returnSomething(int i) { 
// this will be executed asynchronously 
} 

Wie dies korrekt zu implementieren?

Antwort

21

Check out this blog post.

Mit @Async können Sie eine Berechnung in einer Methode asynchron ausführen. Dies bedeutet, dass das Steuerelement sofort an den Aufrufer zurückgegeben wird und der Code in der Methode in einem anderen Thread ausgeführt wird, wenn es (in einer Spring-verwalteten Bean) aufgerufen wird. Der Aufrufer erhält ein Objekt Future, das an die laufende Berechnung gebunden ist und es verwenden kann, um zu überprüfen, ob die Berechnung ausgeführt wird, und/oder auf das Ergebnis zu warten.

Erstellen einer solchen Methode ist einfach. Beschriften Sie es mit @Async und wickeln Sie das Ergebnis in AsyncResult, wie im Blogbeitrag gezeigt.

+1

Das ist, was ich gesucht habe – engma

+0

so bedeutet dies ich kann meine Aufgabe jederzeit stoppen, wenn es nicht schon abgesagt wurde Richtig? – engma

+3

@ Developer106 Ja, Sie können Ihre asynchrone Methode durch Aufruf von [cancel (true)] _interrupt_ (http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#cancel (boolean)) auf dem zurückgegebenen 'Future'. Die Unterbrechung funktioniert jedoch nicht automatisch. Entweder sollte die Methode die Unterbrechung durch Aufruf von 'Thread.isInterrupted()' überprüfen oder Methoden verwenden, die 'InterruptedException' auslösen. Siehe [Interrupts] (http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html) im Java-Tutorial. –

2

Der ExecutorService kann Callable einplanen und ein Future-Objekt zurückgeben. Die Zukunft ist ein Platzhalter, der das Ergebnis enthält, sobald es verfügbar ist. Sie können überprüfen, ob das Ergebnis vorhanden ist, die Aufgabe abbrechen oder blockieren und auf die Ergebnisse warten. Die Zukunft ist nur nützlich, wenn Sie ein Objekt/Wert von der Aufgabe erwarten.

korrekte Weg, um die Zukunft Aufruf zu tun ist:

Future<Integer> futureEvenNumber = executorService.submit(new NextEvenNumberFinder(10000)); 

// Do something. 

try { 
    Integer nextEvenNumber = futureEvenNumber.get(); 
} catch (ExecutionException e) { 
    System.err.println("NextEvenNumberFinder threw exception: " + e.getCause()); 
} 

Die NextEvenNumberFinder Klasse:

public class NextEvenNumberFinder implements Callable<Integer> { 
private int number; 

public NextEvenNumberFinder(int number) { this.number = number; } 

@Override 
public Integer call() throws Exception { 
    for (;;) 
     if (isEvenNumber(++number)) return number; 
} 

}

Frühling Integration Referenzhandbuch: http://static.springsource.org/spring-integration/reference/htmlsingle/

+0

Ich werde meine Antwort aktualisieren, so dass Sie bekommen können, was ich meine – engma

2

Schauen Sie sich diese blog post

Wichtige Konfiguration ist:

  1. @Async auf Frühling Managed Bean Methode
  2. aktivieren async im Frühjahr Config xml durch die Definition:

    <!-- Enables the detection of @Async and @Scheduled annotations on any Spring-managed object. --> 
         <task:annotation-driven/> 
    

    SimpleAsyncTaskExecutor wird standardmäßig verwendet.

Wickeln Sie die Antwort in einer Zukunft <> Objekt

Beispiel:

@Async 
    public Future<PublishAndReturnDocumentResult> generateDocument(FooBarBean bean) { 
//do some logic 
return new AsyncResult<PublishAndReturnDocumentResult>(result); 


} 

können Sie dann prüfen, ob das Ergebnis erfolgt (result.isDone()) oder warten zu bekommen die Antwort result.get()