Llamada asíncrona @Async de SpringBoot
Utilice Spring Initializer para crear un proyecto gradle spring-boot-async-task y agregarle dependencias.
Configure la anotación @EnableAsync en la clase de entrada Spring Boot para habilitar el procesamiento asincrónico.
Cree la clase abstracta de tarea AbstractTask y configure tres métodos de tarea doTaskOne(), doTaskTwo() y doTaskThree().
El siguiente es un ejemplo simple para ilustrar visualmente qué son las llamadas sincrónicas:
Defina una clase de tarea, herede de AbstractTask y use tres controladores para simular las tres operaciones de ejecución de la tarea. , el tiempo consumido por la operación es aleatorio (dentro de 10 segundos).
En el caso de prueba unitaria, inyecta el objeto Task y ejecuta los métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Al ejecutar una prueba unitaria, puede ver un resultado similar al siguiente:
La tarea uno, la tarea dos y la tarea tres se ejecutan en orden; en otras palabras, doTaskOne() , Los métodos doTaskTwo () y doTaskThree() se ejecutan secuencialmente.
Como se puede ver en lo anterior, el tiempo de ejecución es bastante largo. Si no hay dependencia entre las tres tareas, se pueden ejecutar al mismo tiempo, pero las llamadas sincrónicas son menos eficientes, por lo que. puedes considerarlos juntos Ejecutado de forma asincrónica.
Cree una clase AsyncTask y configure la anotación @Async en cada método para cambiar el método sincrónico original a un método asincrónico.
En el caso de prueba unitaria, inyecta el objeto AsyncTask y ejecuta los métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Cuando ejecuta pruebas unitarias, verá un resultado similar al siguiente:
Si ejecuta pruebas unitarias repetidamente, puede encontrar resultados diferentes, como:
La razón es que los métodos doTaskOne(), doTaskTwo() y doTaskThree() se han ejecutado de forma asincrónica. Después de que el programa principal las llama de forma asincrónica, al programa principal no le importa si estas tres funciones se han ejecutado y, como no hay nada más que ejecutar, el programa finalizará automáticamente, lo que dará como resultado un resultado incompleto o nulo relacionado con la tarea.
Según las necesidades comerciales, puede configurar métodos que no necesitan procesarse inmediatamente como @Async.
Por ejemplo, si el usuario hace clic en la interfaz para completar el inicio de sesión, el requisito comercial es finalizar el proceso después de que el inicio de sesión sea exitoso.
De hecho, el éxito o el fracaso del enterramiento no afectará la operación del usuario, por lo que puede configurar el método de enterramiento en @Async.
Personalmente creo que este tipo de tareas suelen tener tres características:
Para que doTaskOne(), doTaskTwo(), doTaskThree() finalicen normalmente, supongamos que necesitamos calcular el número de ejecuciones simultáneas. Necesitamos calcular el tiempo necesario para que se ejecuten tres tareas *** simultáneamente, lo que requiere que esperemos hasta que se utilicen las tres funciones mencionadas anteriormente antes de registrar el tiempo y calcular los resultados.
Entonces, ¿cómo determinamos si estas tres llamadas asincrónicas se han completado? Necesitamos usar Future
En el caso de prueba unitario, inyecta el objeto AsyncCallBackTask y ejecuta los métodos doTaskOneCallback(), doTaskTwoCallback() y doTaskThreeCallback() en el caso de prueba. Llame al método isDone () de Future en un bucle, espere a que se completen tres tareas simultáneas y registre el tiempo de ejecución final.
Registre la hora de inicio al comienzo del caso de prueba; al llamar a tres funciones asincrónicas, devuelva un objeto de resultado de tipo Future, después de llamar a tres funciones asincrónicas, abra un bucle, determinado en función del objeto Future devuelto; Si se completan las tres funciones asincrónicas. Si se completan todos, el ciclo finaliza; si no se completan todos, espere 1 segundo y juzgue nuevamente. Después de salir del bucle, calcule el tiempo total requerido para la ejecución simultánea de las tres tareas en función de la hora de finalización y de inicio.
Al ejecutar la prueba unitaria anterior, puede ver los siguientes resultados:
Como puede ver, la ejecución asincrónica de la Tarea 1, la Tarea 2 y la Tarea 3 acorta efectivamente la duración total de el tiempo de ejecución del programa.
En la operación anterior, cree una clase de configuración de grupo de subprocesos TaskConfiguration y configure un objeto de grupo de tareas taskExecutor.
Arriba, utilizamos ThreadPoolTaskExecutor para crear un grupo de subprocesos y establecer los siguientes parámetros:
Crear AsyncExecutor. p> Cree la clase AsyncExecutorTask y configure las tres tareas de la misma manera que AsyncTask, excepto que la anotación @Async debe especificar el nombre del taskExecutor del grupo de subprocesos que configuramos anteriormente.
En pruebas unitarias En el caso de prueba unitaria, inyecta el objeto AsyncExecutorTask y ejecuta los métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Ejecute la prueba unitaria anterior y vea los siguientes resultados:
Ejecute la prueba unitaria anterior y observe que se imprime el prefijo del nombre del grupo de subprocesos del grupo de subprocesos de la tarea, lo que indica ¡Que el grupo de subprocesos ejecutó con éxito tareas asincrónicas!
La solución es la siguiente: restablecer el objeto de configuración del grupo de subprocesos y agregar una nueva configuración setWaitForTasksToCompleteOnShutdown() y setAwaitTerminationSeconds() del grupo de subprocesos: