springboot requestmapping example enableasync ejemplo async spring spring-mvc asynchronous transactions spring-annotations

requestmapping - Spring @Async cancelar e iniciar?



spring boot rest asynchronous (2)

De la documentación sobre el método cancel() ,

Las llamadas posteriores a isCancelled () siempre devolverán true si este método devuelve true

Prueba esto.

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 }

Tengo una aplicación de primavera MVC donde un usuario puede iniciar una generación de informes con un clic en el botón. Este proceso podría tomar algunos minutos ~ 10-20 minutos. Utilizo la anotación springs @Async alrededor de la llamada de servicio para que la generación de informes se realice de forma asíncrona. Mientras le aparece un mensaje al usuario indicando que el trabajo se está ejecutando actualmente. Ahora lo que quiero hacer es si otro usuario (Admin) puede iniciar la generación de informes mediante el botón que debería cancelar / detener la ejecución actual de la tarea @Async y reiniciar la nueva tarea. Para hacer esto, yo llamo al

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

¿Cómo se puede hacer para que "service.generateReport" espere mientras que la tarea de cancelación futura mata a todos los hilos en ejecución? De acuerdo con la documentación, después de que llame a future.cancel (true), isDone devolverá true, así como isCancelled devolverá true. Por lo tanto, no hay forma de saber que el trabajo en realidad se canceló.

Solo puedo comenzar la generación de un nuevo informe cuando el anterior se cancela o completa para que no se ensucien los datos.


Suponiendo que el código anterior se ejecuta en el subproceso A, y su informe cancelado recientemente se está ejecutando en el subproceso B, entonces necesita el subproceso A para detenerse antes de service.generateReport(id) y esperar hasta que el subproceso B se complete / cancele.

Un enfoque para lograr esto es usar Semáforo. Suponiendo que solo puede haber 1 informe ejecutándose simultáneamente, primero cree un objeto de semáforo accesible por todos los hilos (normalmente en la clase de servicio del corredor de informes)

Semaphore semaphore = new Semaphore(1);

En cualquier punto de su código donde necesite ejecutar el informe, llame al método acquire() . Este método se bloqueará hasta que haya un permiso disponible. Del mismo modo, cuando la ejecución del informe finaliza / cancela, asegúrese de llamar a release() . El método de liberación devolverá el permiso y activará otro hilo en espera.

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