Hoy aprenderemos cómo realizar una programación asincrónica en primavera. Todos sabemos que los subprocesos de que el servidor web procesa request solicitudes se obtiene del grupo de subprocesos, lo cual no es difícil de explicar, porque cuando el número de solicitudes web es muy grande, cómo crear un hilo de procesamiento cuando entre una solicitud. Dado que la sobrecarga de la creación de subprocesos y el cambio de contexto de hilos es relativamente grande, el servidor web eventualmente enfrentará un bloqueo. Además, los subprocesos de procesamiento creados por el servidor web se ejecutan sincrónicamente de principio a fin. Es decir, si el subproceso de procesamiento A es responsable de la solicitud de procesamiento B, entonces, cuando B no return , el subproceso de procesamiento A no puede escapar para procesar otras solicitudes, lo que limitará en gran medida la capacidad de procesamiento concurrente del servidor web.
Por lo tanto, el grupo de subprocesos resuelve el problema del reciclaje de hilos, entonces, ¿cómo resolver la solicitud de procesamiento sincrónico? La respuesta es el procesamiento asíncrono. ¿Qué es el procesamiento asincrónico? El procesamiento asincrónico permite principalmente que la solicitud B anterior esté inactiva antes de que se complete el procesamiento de solicitud anterior, y el subproceso A se puede liberar para continuar procesando otras solicitudes. Luego podemos hacer esto, reiniciar el subproceso C dentro del subproceso A para ejecutar la tarea, dejar que regrese directamente al servidor web y continúe aceptando nuevas solicitudes.
Antes de comenzar la explicación a continuación, primero distinguiré dos conceptos aquí:
1. Procesar hilos
El hilo de procesamiento pertenece al servidor web, es responsable del procesamiento de solicitudes de usuarios y es administrado por Thread Pool
2. Enhebramiento asíncrono
Los subprocesos asíncronos son hilos definidos por el usuario y pueden ser administrados por Pools de subprocesos.
Spring proporciona soporte para tareas asincrónicas. Las tareas asíncronas se pueden implementar utilizando la clase WebAsyncTask . Al mismo tiempo, también podemos establecer el procesamiento de devolución de llamada correspondiente para tareas asincrónicas, como cómo manejar cuando la tarea se agotó y cómo lanzar una excepción. Las tareas asincrónicas suelen ser muy prácticas. Por ejemplo, queremos dejar una operación que pueda procesarse durante mucho tiempo para que el hilo asíncrono se procese, o cuando se paga un pedido, habilitamos la tarea asíncrona para consultar el resultado del pago del pedido.
1. Tareas asincrónicas normales
Para conveniencia de demostración, la ejecución de tareas asincrónicas se simula usando Thread.sleep(long) . Ahora suponga que el usuario solicita la siguiente interfaz:
http://localhost:7000/demo/getUserWithNoThing.json
La interfaz de tarea asíncrona se define de la siguiente manera:
/*** Pruebe tareas asíncronas sin ninguna excepción*/@requestmapping (value = "getUserWithNothing.json", método = requestMethod.get) public WebAsyncTask <String> getUserWithNothing () {// imprime el nombre del hilo System.err.println ("El nombre del hilo principal es" + Thread.CurrentThread (). GetName (); // Esto simula la apertura de una tarea asíncrona, con un tiempo de espera de 10s WebAsyncTask <String> tarea1 = new WebAsyncTask <String> (10 * 1000L, () -> {System.err.println ("El primer nombre de subproceso" + hilo.currentThread (). "¡La tarea 1 se ejecuta con éxito! ¡No se lanza la excepción!"; // El método se llama cuando la ejecución de la tarea se completa tarea1.onCompletion (() -> {System.err.println ("Tarea 1 se ejecuta completado!");}); System.err.println ("¡Tarea1 continúa manejando otras cosas!"); Tarea de retorno1;}La consola se imprime de la siguiente manera:
El nombre del hilo principal es HTTP-NIO-7000-EXEC-1
¡Tarea1 sigue tratando con otras cosas!
El primer nombre del hilo es MVCasync1
¡La tarea 1 se ha completado!
Los resultados del navegador son los siguientes:
2. Excepción de la tarea asincrónica de excepción
Llamada a la interfaz: http://localhost:7000/demo/getUserWithError.json
/*** Pruebe la tarea asíncrona donde ocurre un error* @return*/ @requestmapping (value = "getUserWitherror.json", método = requestmethod.get) public WebasyncTask <String> getUserWitherror () {system.err.println ("El nombre del hilo principal es" + thread.currentthread (). GetName ()); Tarea asíncrona. WebAsyncTask<String> task3 = new WebAsyncTask<String>(10 * 1000L, () -> {System.err.println("The second Thread name is " + Thread.currentThread().getName());// Exception thrown here int num = 9 / 0;System.err.println(num);return "";});// Call this method when an exception occurs task3.onError(() -> {System.err.println("==================================================================================== ==================================================================================================================================================================================================================================================================================================. ==================================================================================================================================================================================================================================================================================================. ========================================================================================================== "================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ======================================================================La salida de la consola es la siguiente:
El nombre del hilo principal es HTTP-NIO-7000-EXEC-1
¡Task3 continúa lidiando con otras cosas!
El nombre del segundo hilo es MVCasync1
2018-06-15 09: 40: 13.538 Error 9168 --- [NIO-7000-EXEC-2] OACCC [. [. [DispatcherServlet]: servlet.service () para servlet [despachador] Excepción de lanzamientojava.lang.arithmeticexception: / por cero
en com.example.demo.controller.getuserInfocontroller.lambda $ 5 (getUserInfocontroller.java:93) ~ [clases/: na]
en org.springframework.web.context.request.async.webasyncmanager.lambda $ startcallableprocessing $ 4 (webasyncmanager.java:317) ~ [spring-web-5.0.6.release.jar: 5.0.6.reelease]
en java.util.concurrent.executors $ runnableadapter.call (ejecutors.java:511) ~ [na: 1.8.0_161]
en java.util.concurrent.futuretask.run (futuretask.java:266) ~ [na: 1.8.0_161]
en java.lang.thread.run (Thread.java:748) [NA: 1.8.0_161]2018-06-15 09: 40: 13.539 Error 9168 --- [NIO-7000-EXEC-2] OACCC [. [. La excepción anidada es java.lang.arithmeticException: / por cero] con causa raíz
java.lang.arithmeticexception: / por cero
en com.example.demo.controller.getuserInfocontroller.lambda $ 5 (getUserInfocontroller.java:93) ~ [clases/: na]
en org.springframework.web.context.request.async.webasyncmanager.lambda $ startcallableprocessing $ 4 (webasyncmanager.java:317) ~ [spring-web-5.0.6.release.jar: 5.0.6.reelease]
en java.util.concurrent.executors $ runnableadapter.call (ejecutors.java:511) ~ [na: 1.8.0_161]
en java.util.concurrent.futuretask.run (futuretask.java:266) ~ [na: 1.8.0_161]
en java.lang.thread.run (Thread.java:748) [NA: 1.8.0_161]=================================================================================================================================================================================================================================================.
¡La misión 3 ha ocurrido!
¡La tarea 3 se ha completado!
Por supuesto, también puede hacer un manejo de excepciones sobre lo anterior para evitar hostil en la opinión del usuario. Para el manejo de excepciones, puede consultar otro artículo en mi artículo sobre el uso del esquema de manejo de errores unificados de arranque de primavera/primavera
Resultados de salida del navegador:
3. Tiempo de espera asincrónico
Llamada a la interfaz: http://localhost:7000/demo/getUserWithTimeOut.json
/*** Pruebe la tarea asíncrona en la que la tarea cronometró* @return*/ @requestmapping (value = "getUserWithtimeout.json", método = requestmethod.get) public WebasyncTask <string> getUserWithTimeOut () {System.err.println ("El nombre principal del hilo" es " + Thread.CurrentThread (). GetName ());); // Esto se simula para iniciar una tarea asíncrona, tiempo de espera de 10s WebAsyncTask <String> tarea2 = new WebAsyncTask <String> (10 * 1000l, () -> {System.err.println ("El segundo nombre de hilo es" + hilo.currentThread (). // El tiempo de espera de la tarea llama a este método Tarea2.ontimeout (() -> { System.err.println ("============================================================================================================================================================= ========================================================================================================== ========================================================================================================== ========================================================================================================== "================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ====================================================================== ======================================================================Resultados de la ejecución de la consola:
El nombre del hilo principal es HTTP-NIO-7000-EXEC-4
¡Tarea2 continúa lidiando con otras cosas!
El nombre del segundo hilo es MVCasync2
====================================================================================================================================================================== ¡
¡La tarea 2 se ha completado!
Resultados de la ejecución del navegador:
4. Tareas asíncronas del grupo de hilos
Las tareas asincrónicas en los tres casos anteriores no son administradas por el mecanismo de grupo de subprocesos de forma predeterminada. Es decir, si entra una solicitud, aunque se libera el hilo de procesamiento, el sistema aún creará un hilo de tarea asíncrono para cada solicitud, que es el hilo de tareas asincrónico que comienza con MvcAsync como vimos anteriormente. Es decir, esto no funcionará, ¡la sobrecarga es particularmente alta! Por lo tanto, podemos usar el grupo de hilos para la administración y pasar directamente una instancia de objeto ThreadPoolTaskExecutor en el constructor de clase WebAsyncTask .
Primero veamos lo que sucede al realizar solicitudes concurrentes en el primer caso anterior (aquí simulamos llamadas concurrentes a http://localhost:7000/demo/getUserWithNoThing.json )::
La salida de la consola es la siguiente:
El primer nombre del hilo es MVCasync57
El primer nombre del hilo es MVCasync58
El primer nombre del hilo es MVCasync59
El primer nombre del hilo es MVCasync60
El primer nombre del hilo es MVCasync61
El primer nombre del hilo es MVCasync62
El primer nombre del hilo es MVCasync63
El primer nombre del hilo es MVCasync64
El primer nombre del hilo es MVCasync65
El primer nombre del hilo es MVCasync66
El primer nombre del hilo es MVCasync67
El primer nombre del hilo es MVCasync68
El primer nombre del hilo es MVCasync69
El primer nombre del hilo es MVCasync70
El primer nombre del hilo es MVCasync71
El primer nombre del hilo es MVCasync72
El primer nombre del hilo es MVCasync73
El primer nombre del hilo es MVCasync74
El primer nombre del hilo es MVCasync76
El primer nombre del hilo es MVCasync75
El primer nombre del hilo es MVCasync77
El primer nombre del hilo es MVCasync78
El primer nombre del hilo es MVCasync79
El primer nombre del hilo es MVCasync80
Dado que no se agrega el grupo de subprocesos, 100 solicitudes abrirán 100 hilos de tareas asincrónicas, que son particularmente caros y no se recomienda.
La siguiente es la implementación de Thread Pool:
Interfaz de llamada: http://localhost:7000/demo/getUserWithExecutor.json
/*** Test Hilt Pool* @return*/ @requestmapping (value = "getUserWithExecutor.json", método = requestMethod.get) public WebasyncTask <String> getUserWitHeCutor () {System.err.println ("El nombre del hilo principal es" + Thread.CurrentThread (). GetName ()); // Esto se simula para iniciar una tarea asincrónica, y se pasa un grupo de hilos aquí. WebasyncTask <String> task1 = new WebAsyncTask <String> (10 * 1000L, ejecutor, () -> {System.err.println ("El primer nombre de subproceso es" + Thread.CurrentThread (). // Llame a este método cuando la ejecución de la tarea se complete tarea1.onCompletion ((() -> {System.err.println ("Tarea 4 se ejecuta completado!");}); System.err.println ("¡Tarea4 continúa manejando otras cosas!"); Tarea de retorno1;}La piscina de hilo se define de la siguiente manera:
@ConfigurationPublic Class myExecutor {@Bean public static threadpoolTaskExecutor getExecutor () {ThreadPoolTASKEXECutor TaskExecutor = new ThreadPoolTASKEXECUTOR (); taskexecutor.setCorepoolSize (30); taskexecutor.setMaxPoolSize (30); taskexecutor.setqueueCapacity (50); TaskExecutor.setThreadNamePrefix ("Huang"); // El nombre del hilo de tarea asíncrono es el prefijo de return taskexecutor; }}Las pruebas concurrentes anteriores se pueden usar para obtener los siguientes resultados:
La dirección del código de muestra de este artículo: https://github.com/smallercoder/webasynctask
El uso de grupos de subprocesos puede guardar recursos del servidor y optimizar las capacidades de procesamiento del servidor. ¡Recuerda usarlos con frecuencia! ¡Gracias por leer! Si cree que será útil para usted, ¡comience!
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.