Un artículo sobre cómo resolver el problema de la "alta concurrencia"

Hablando de "alta concurrencia" , basta con considerarlo como un término de red que ha sido popular en el mundo de la programación en los últimos años. Después de todo, con el rápido desarrollo de Internet, especialmente el rápido desarrollo de las aplicaciones de la plataforma de comercio electrónico, el contenido de los servicios de Internet es cada vez más abundante y el número de usuarios de la plataforma está aumentando. Taobao, Tmall, Jingdong, " Pixixixi ", Shaking Sounds y demás son aplicaciones de nivel casi nacional que las masas de personas deben utilizar todos los días.

 

En estas aplicaciones, los eventos a gran escala como "Tmall Double 11", "Jingdong 618", "Seckill de productos básicos", "Toma de boletos de tren" y otros eventos a gran escala a menudo se concentran en un corto período de tiempo, una gran cantidad de visitas concurrentes, afrontando estos momentos Si la afluencia de tráfico de usuarios y las necesidades de acceso no se pueden resolver adecuadamente, será como el anterior crash de Tmall Double 11, que no solo afecta la experiencia del usuario, sino que también frustra las actividades normales y reduce enormemente la rotación. ..

 

Y cómo resolver este tipo de problema de alta concurrencia, la primera base es poder jugar con hilos; por lo tanto, para el contenido de hoy, aprenderemos el conocimiento seco sobre hilos:

 

1. ¿Por qué debería haber hilos?

 

Regala una castaña: Abrimos la aplicación Baidu Netdisk y queremos usar las funciones de carga y descarga.

 

Si no hay hilo, nuestra operación es así: cuando cargamos archivos, no podemos hacer otras cosas, necesitamos cargar con éxito antes de poder descargar otras cosas, y los archivos cargados solo se pueden cargar uno por uno, lo hará ser muy mala experiencia

 

Y qué pasa si queremos lograr la función de cargar y descargar al mismo tiempo, y múltiples cargas y múltiples descargas.

 

¡Así es! ¡Solo usa hilos!

 

El sistema operativo actual, ya sea Windows o Linux, es básicamente un sistema operativo multiusuario multitarea, y la multitarea se realiza mediante subprocesos múltiples, la ejecución multitarea también se denomina "concurrencia".

 

2. La diferencia entre proceso e hilo

 

Cuando se trata de hilos, primero tenemos que mencionar los procesos. Mucha gente piensa que un proceso es un programa. ¿No es lo mismo?

 

No se preocupe, echemos un vistazo a la definición de proceso:

 

● Resumen del proceso

 

El programa que puede ejecutarse de forma independiente en el sistema se denomina proceso, y el proceso también es la unidad más pequeña de recursos de asignación de CPU;

 

Por ejemplo, estamos familiarizados con el proceso de Windows a diario:

 

 

Cada proceso tiene su propio espacio de memoria independiente. Una CPU de un solo núcleo es un procesamiento de un solo proceso, es decir, solo se puede procesar un proceso al mismo tiempo, pero el sistema puede asignar una cantidad limitada de tiempo para ejecutar la CPU para cada proceso (llamado intervalo de tiempo de CPU), la CPU ejecuta un determinado proceso durante este período de tiempo, y luego puede saltar a otro proceso para ejecutar en el siguiente período de tiempo, porque la velocidad de conmutación de la CPU es demasiado rápida, mucho más allá del reconocimiento capacidad de nuestros ojos desnudos Entonces vemos que muchos procesos parecen estar ejecutándose al mismo tiempo.

 

La CPU de varios núcleos puede realizar la ejecución de varios procesos al mismo tiempo, pero debido a problemas de programación, un núcleo puede llamar a varios procesos en un intervalo de tiempo.

 

● Descripción general de los hilos

 

El hilo es la tarea de ejecución de completar un proceso en el proceso, es una ruta de ejecución en el proceso y comparte un espacio de memoria con el proceso. Un hilo es la unidad más pequeña que se ejecuta en un programa.

 

El hilo en sí no puede existir solo y debe ejecutarse en el proceso. Un proceso puede tener varios subprocesos (por ejemplo: un programa Java básicamente tiene dos o más subprocesos, como el subproceso principal y el subproceso GC [recolector de basura]), y todos los subprocesos del mismo proceso comparten los recursos del proceso.

 

3. Implementación de subprocesos en Java

 

A través de la introducción anterior, conocemos el hilo, entonces, ¿cómo se implementa el hilo en Java?

 

De hecho, hay tres formas principales de implementar subprocesos en Java:

 

● Heredar la clase Thread

● Implementar la interfaz ejecutable

● Implementar la interfaz invocable

 

Las dos primeras implementaciones son más comunes y las clases e interfaces también están en el paquete java.long. El tercero Callable está en el paquete java.util.concurrent. Presentaremos su implementación y diferencias en la última parte;

 

Veamos las dos primeras implementaciones:

 

(1) Heredar la clase Thread

 

Primero que nada, vemos que la clase Thread también implementa la interfaz Runnable

 

 

Para que podamos usarlo directamente creando un objeto Thread.

 

Pasos de uso:

 

A. Heredar la clase Thread o crear un objeto Thread directamente

B. Implementar código de tarea de subproceso en el método de ejecución

C. Llame al método de inicio de Thread para iniciar el hilo

 

el código se muestra a continuación:

 

También se puede usar directamente con new Thread, el código es el siguiente:

 

 

Análisis: El siguiente método no necesita definir la clase a utilizar más simple, adecuado para el caso de menos llamadas. Además, aunque el método de ejecución se ejecuta después de que se inicia el subproceso de la clase Thread, el método de inicio del subproceso es el método de inicio.

 

La diferencia entre el método de inicio y el método de ejecución:

 

El método de ejecución es solo un método ordinario de la clase Thread pura, pero se llamará cuando se inicie el hilo. Si solo usamos thread.run (), entonces solo significa que hemos llamado al método de ejecución del hilo pero no se inició. un nuevo hilo El código todavía se ejecuta en el hilo principal main.

 

La llamada al método de inicio significa que se crea un nuevo subproceso y el subproceso entra en el estado listo. Cuando el subproceso obtiene el procesamiento del intervalo de tiempo de la CPU, la máquina virtual Java llamará al método de ejecución del subproceso y ejecutará el código de la tarea en su interior. El subproceso será se ejecuta después de que se ejecuta el código de la tarea. Además, el nuevo hilo abierto por inicio es una tarea de ejecución independiente, y el siguiente código puede continuar la ejecución sin esperar a que se complete la ejecución del hilo.

 

Limitaciones de usar la clase Thread:

 

Aunque la implementación de la clase Thread es simple, debido a que Thread es una clase, la clase solo puede llevar a cabo una herencia única en Java, por lo que la escalabilidad de los subprocesos es pobre.

 

(2) Implementar interfaz Runable

 

Runnable es una interfaz funcional (modificada por @FunctionalInterface y solo un método abstracto). La definición es muy simple y solo tiene un método de ejecución. El código fuente es el siguiente:

 

 

Antes, también introdujimos que la clase Thread realmente implementa la interfaz Runable. El método de ejecución que inicia el hilo para ejecutar el código de la tarea es en realidad el método de interfaz Runnable. Entonces podemos implementar el uso extendido de subprocesos implementando la interfaz Runable con la clase Thread.

 

Pasos de uso:

 

A. Definir una clase que implemente la interfaz Runnable

B. Implementar código de tarea de subproceso en el método de ejecución

C.Pasar el objeto de instancia de la interfaz Runnable a través del método de construcción Thread (Runnable r) y llamar al método de inicio para iniciar el hilo.

 

el código se muestra a continuación:

 

 

 análisis:

Usando la implementación de la interfaz Runnable, debido a las características de la interfaz se puede implementar más, la interfaz Runnable se puede implementar con más clases, y su escalabilidad es más fuerte que la de Thread. Además, debido a que Runnable es un hilo creado cuando se pasa como método de construcción de Thread, Runnable debe ser dependiente Usado con la clase Thread, y varios objetos Thread pueden usar la misma instancia de Runnable.

 

Uso de la expresión Lambda de Runnable:

 

Java8 proporciona expresiones Lambda. Cuando usamos expresiones Lambda para crear instancias de clases de implementación de Runable, no necesitamos definir la clase, lo que resulta más conveniente.

 

El código se implementa de la siguiente manera:

 

4. Caso de venta de boletos de caja clásica de múltiples subprocesos

 

Aunque los subprocesos se pueden implementar heredando la clase Thread e implementando la interfaz Runnable en desarrollo, existen limitaciones para heredar la clase Thread. La implementación de la interfaz Runnable es más fácil de extender y la instancia que implementa la interfaz Rnnnable puede ser compartida por múltiples objetos Thread, lo que hace que sea más conveniente resolver algunos recursos de procesamiento multiproceso. Ilustremos con un caso de venta de entradas:

 

Tenemos tres ventanillas de venta de entradas, con un total de 100 entradas ¿Cómo lograr que las tres ventanillas se vendan al mismo tiempo y se vendan 100 entradas?

 

(1) Implementación de la clase Thread

 

 

El resultado de ejecutar:

 

 

En conclusión:

Finalmente, encontré que cada ventana vendió 100 boletos, se vendieron un total de 300 boletos, pero solo había 100 boletos en total. Obviamente, es inconveniente heredar la clase Thread, porque los tres hilos de ventana t1, t2 y t3 no pueden compartir 100 boletos, recursos, por lo que cada uno vendió 100 copias.

 

(2) Implementación de la interfaz Runnable

 

 

El resultado de ejecutar:

 

 

En conclusión:

 

Descubrimos que el uso de la interfaz Runnable permite que los tres subprocesos de ventana t1, t2 y t3 vendan 100 boletos al mismo tiempo, en lugar de vender 100 boletos por cada subproceso. Esto se debe a que t1, t2 y t3 usan el mismo Runnable instancia.

 

Obviamente la implementación de la interfaz Runnable puede realizar el intercambio de 100 recursos de ticket, pero a través de los resultados de la operación encontraremos un problema confuso, es decir, no importa cuántas veces se ejecute el programa, siempre hay dos o tres subprocesos vendiendo el mismo boleto!

 

¿Qué causó esto?

 

De hecho, este es el llamado "problema de acceso concurrente de subprocesos múltiples inseguros".

 

De acuerdo, este problema del intercambio de productos secos termina aquí. En los siguientes capítulos, presentaremos por qué el acceso de varios subprocesos a los objetos no es seguro. Los amigos interesados ​​pueden prestar atención a una ola. Nos vemos en el próximo número ~

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43802541/article/details/112323985
Recomendado
Clasificación