Llamada asíncrona @Async de SpringBoot
Utilice Spring Initializer para crear un proyecto gradle spring-boot-async-task y agregue dependencias relevantes al crearlo.
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() respectivamente.
Entendamos intuitivamente qué son las llamadas sincrónicas a través de un ejemplo simple:
Defina la clase Task y herede AbstractTask Las tres funciones de procesamiento simulan las operaciones de tres tareas de ejecución respectivamente. El tiempo se elige al azar (dentro de los 10 segundos).
En el caso de prueba unitaria, inyecte el objeto Task y ejecute los tres métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Cuando ejecuta la prueba unitaria, puede ver un resultado similar al siguiente:
La tarea uno, la tarea dos y la tarea tres se ejecutan en secuencia; en otras palabras, doTaskOne() , doTaskTwo(), doTaskThree() Se completa la ejecución secuencial de los tres métodos.
De lo anterior se puede ver que el tiempo de ejecución es relativamente largo. Si no hay dependencia entre las tres tareas y se pueden ejecutar al mismo tiempo, la eficiencia de ejecución de las llamadas sincrónicas será relativamente pobre. Puede considerar utilizar llamadas asincrónicas para ejecutarlas al mismo tiempo.
Cree la clase AsyncTask, configure las anotaciones @Async en los métodos y cambie el método sincrónico original a un método asincrónico.
En el caso de prueba unitaria, inyecte el objeto AsyncTask y ejecute los tres métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Cuando ejecuta las pruebas unitarias, puede ver un resultado similar al siguiente:
Si ejecuta las pruebas unitarias repetidamente, puede encontrar varios resultados diferentes, como por ejemplo:
La razón es que los tres métodos doTaskOne(), doTaskTwo() y doTaskThree() actualmente se ejecutan de forma asincrónica. Después de llamar al programa principal de forma asincrónica, al programa principal no le importa si se completa la ejecución de estas tres funciones. Dado que no hay otro contenido que deba ejecutarse, el programa finaliza automáticamente, lo que resulta en una tarea incompleta o nula. contenido relacionado.
Según los requisitos comerciales, puede configurar el método que no necesita procesamiento inmediato en @Async.
Por ejemplo, si el usuario hace clic en la interfaz para completar la operación de inicio de sesión. Luego, de acuerdo con los requisitos comerciales, es necesario realizar el proceso de enterramiento de puntos después de iniciar sesión correctamente.
De hecho, si el enterramiento de puntos es exitoso o no, no afecta la operación del usuario. En este momento, el método de enterramiento de puntos se puede configurar en @Async.
Personalmente creo que estas tareas suelen tener tres características:
Para doTaskOne (), doTaskTwo () y doTaskThree (). ) para finalizar normalmente, supongamos que necesitamos contar cuánto tiempo lleva ejecutar tres tareas al mismo tiempo. Aquí debe esperar hasta que se hayan utilizado las tres funciones anteriores para registrar el tiempo y calcular los resultados.
Entonces, ¿cómo juzgamos si las tres llamadas asincrónicas anteriores se han completado? Necesitamos usar Future
En el caso de prueba unitaria, inyecte el objeto AsyncCallBackTask y ejecute los tres métodos doTaskOneCallback(), doTaskTwoCallback() y doTaskThreeCallback() en el caso de prueba.
El método isDone() de Future se llama en un bucle para esperar a que se complete la ejecución de tres tareas simultáneas y se registra 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 Futuro después de llamar a las tres funciones asincrónicas, inicie un bucle, basado en el objeto Futuro devuelto; determine si las tres funciones asincrónicas han finalizado. Si ya terminaron, finaliza el ciclo; si no, espera 1 segundo antes de tomar una decisión. Después de salir del ciclo, calcule el tiempo total necesario para ejecutar las tres tareas simultáneamente según la hora de finalización y la hora de inicio.
Ejecute la prueba unitaria anterior y podrá ver los siguientes resultados:
Puede ver que a través de llamadas asincrónicas, la tarea uno, la tarea dos y la tarea tres se ejecutan simultáneamente, lo que efectivamente reduce el tiempo total 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 subprocesos de tarea taskExecutor.
Arriba creamos un grupo de subprocesos usando ThreadPoolTaskExecutor y configuramos los siguientes parámetros:
Cree la clase AsyncExecutorTask, la configuración de las tres tareas es la misma que AsyncTask, la diferencia es @Async La anotación debe especificar el nombre del grupo de subprocesos configurado previamente, taskExecutor.
En el caso de prueba unitaria, inyecte el objeto AsyncExecutorTask y ejecute los tres métodos doTaskOne(), doTaskTwo() y doTaskThree() en el caso de prueba.
Ejecute la prueba unitaria anterior y podrá ver 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 la tarea asincrónica del grupo de subprocesos se ejecutó correctamente.
La solución es la siguiente: restablecer el objeto de configuración del grupo de subprocesos y agregar las configuraciones setWaitForTasksToCompleteOnShutdown() y setAwaitTerminationSeconds() del grupo de subprocesos: