Spring @Async undo and run?

I have a spring MVC application where a user can start generating a report with the click of a button. This process may take several minutes ~ 10-20 minutes. I use springs @ Async annotation around a service call, so reporting is asynchronous. While I am leaving a message to the user, indicating that the work is currently running. Now, what I want to do if another user (administrator) can start generating a report with a button that should cancel / stop the current @Async task and restart the new task. For this I call

.. .. future = getCurrentTask(id); // returns the current task for given report id if (!future.isDone()) future.cancel(true); service.generateReport(id); 

How to do this so that "service.generateReport" waits until the cancel task cancels all running threads? According to the documentation, after I called future.cancel (true), isDone will return true, and isCancelled will return true. Thus, there is no way to know that the work is actually canceled.

I can only start creating a new report when the old one is canceled or completed so that it does not pollute the data.

+3
source share
2 answers

From the documentation for the cancel() method,

Subsequent calls to isCancelled () will always return true if this method returned true

Try it.

 future = getCurrentTask(id); // returns the current task for given report id if (!future.isDone()){ boolean terminatedImmediately=future.cancel(true); if(terminatedImmediately) service.generateReport(id); else //Inform user existing job couldn't be stopped.And to try again later } 
+2
source

Assuming the above code is running on thread A and your recently canceled report is running on thread B, you need thread A to pause before service.generateReport(id) and wait for thread B to finish / cancel.

One way to achieve this is to use Semaphore. Assuming that only one report can work at a time, first create a semaphore object that is accessible to all threads (usually in the report search service class)

 Semaphore semaphore = new Semaphore(1); 

At any point in your code where you need to run the report, call the acquire() method. This method blocks until permission is available. Similarly, when report execution is completed / canceled, make sure release() called. The Release method will return the resolution and wake up another waiting thread.

 semaphore.acquire(); // run report.. semaphore.release(); 
0
source

All Articles