Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Cancel @Async Task

I want to be able to cancel a method marked with the @Async annotation by it's future.

I have a Spring method marked with the @Async annotation. This method does some computation, and eventually returns a result. All examples I have seen recommend using the AsyncResult class to return this Future.

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

I call the following method, from another Component, in the following manner. For example purposes, I wish to immediately cancel this thread:

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

In this case, the thread will never be cancelled. This is because, looking at the Spring implementation for AsyncResult here: https://github.com/spring-projects/spring-framework/blob/master/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncResult.java#L71 , this method doesn't actually do a single thing. It simply returns false, that the thread could not be cancelled. This is my problem. How can I cancel the Thread being created by the @Async method? I have no access to the internal thread being created by Spring - so I have no means myself with which to cancel it, do I?

like image 881
Patrick D Avatar asked Aug 10 '16 17:08

Patrick D


Video Answer


1 Answers

Actually, Spring @Async uses a background thread pool of it's own. And as long as cancel() method of Future or shutdownNow() of executor service is concerned, Calling executor.shutdownNow() or future.cancel(true) don’t stop the ongoing thread immediately. What these methods do is simply call .interrupt() on the respective thread(s). And interrupts has no guaranteed immediate effect. It issues a flag so whenever in sleeping or waiting state, the thread will be stopped.

To be noted, If your tasks ignore the interruption, executor.shutdownNow() and future.cancel(true) will behave exactly the same way as executor.shutdown() and future.cancel(false).

If you need a way to stop the slow or blocking operation. If you have a long/endless loop, you can just add a condition whether Thread.currentThread().isInterrupted() and don’t continue if it is true(end the operation).

like image 162
Prateek Talesara Avatar answered Sep 19 '22 12:09

Prateek Talesara