2016-08-10 28 views
5

Chcę móc anulować metodę oznaczoną adnotacją @Async według jej przyszłości.Spring Cancel @Async Task

Mam metodę Spring oznaczoną adnotacją @Async. Ta metoda wykonuje pewne obliczenia i ostatecznie zwraca wynik. Wszystkie przykłady, które widziałem, polecają użycie klasy AsyncResult, aby zwrócić tę Przyszłość.

@Async 
public Future<String> run() { 
    // ... Computation. Minutes pass ... 
    return new AsyncResult<String>("Result"); 
} 

Następującą metodę nazywam z innego komponentu w następujący sposób. Na przykład, chcę natychmiast anulować ten wątek:

Future<String> future = component.run(); 
future.cancel(true); 

W takim przypadku wątek nigdy nie zostanie anulowany. Wynika to z tego, że patrząc na wiosenną implementację dla AsyncResult tutaj: https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncResult.java#L71, ta metoda w rzeczywistości nie czyni nic. Zwraca false, że wątku nie można anulować. To jest mój problem. Jak mogę anulować wątek tworzony przez metodę @Async? Nie mam dostępu do wewnętrznej nitki tworzonej przez Spring - więc nie mam środków, dzięki którym mogę ją anulować, prawda?

+0

sprawdź te 2 odpowiedzi [tutaj] (http://stackoverflow.com/questions/21084195/spring-async-cancel-and-start) i [tutaj] (http://stackoverflow.com/questions/35798987/ stop-an-async-spring-method-from-caller-class), lub stwórz niestandardowy "ThreadPoolExecutor", aby obsłużyć metody z adnotacjami @ @ Async lub przeprowadź niestandardowe 'AsyncResult', które będzie wiązało się z uruchomionym zadaniem. – AntJavaDev

+0

Odpowiedzi w tych pytaniach wydają się opisywać tworzenie flagi/semafora w celu poinformowania działającego wątku o zaprzestaniu przetwarzania w późniejszym czasie. Różni się to od zakończenia wątku, ponieważ metoda Future.cancel() działałaby w zdefiniowanym 'Runnieble'. Czy możesz wyjaśnić nieco dalej, jak wyglądałby niestandardowy "ThreadPoolExecutor"? Ja także definiuję swojego własnego Egzekutora, więc dodanie do niego nie będzie trudne ani niewygodne. –

Odpowiedz

4

Faktycznie, wiosna @Async wykorzystuje pulę wątków tła z własnej. A jeśli chodzi o metodę cancel() Future lub shutdownNow() usługi executora, wywołanie executor.shutdownNow() or future.cancel(true) nie zatrzymuje natychmiast bieżącego wątku. Metody te to po prostu wywołanie .interrupt() w odpowiednim wątku (wątkach). I interrupts ma nie gwarantuje natychmiastowego efektu. Wydaje flagę, więc w stanie uśpienia lub oczekiwania wątek zostanie zatrzymany.

Należy zauważyć, jeśli twoje zadania ignorują przerwanie, executor.shutdownNow() and future.cancel(true) zachowuje się dokładnie tak samo, jak executor.shutdown() and future.cancel(false).

Jeśli potrzebujesz sposobu na zatrzymanie powolnej lub blokującej operacji. Jeśli masz długą/nieskończoną pętlę, możesz po prostu dodać warunek, czy Thread.currentThread().isInterrupted() i nie kontynuować, jeśli jest prawdą (zakończyć operację).

+0

Świetnie. Dodałem kontrole boolowskie dla "Thread.interrupted()" w całej mojej logice metody '@ Async'; i jeśli wykryję przerwanie, mogę bezpiecznie oderwać metodę i anulować wykonanie. –