Galería de mapas mentales Mapa mental del mapa de conocimiento del sistema de concurrencia de Java (programación concurrente)
Este es un mapa mental sobre el mapa de conocimiento del sistema de concurrencia Java (programación concurrente), que incluye colas de bloqueo, conceptos básicos de concurrencia, bloqueos, modelo de memoria JAVA y otros aspectos del conocimiento.
Editado a las 2023-11-06 19:35:07,El cáncer de pulmón es un tumor maligno que se origina en la mucosa bronquial o las glándulas de los pulmones. Es uno de los tumores malignos con mayor morbilidad y mortalidad y mayor amenaza para la salud y la vida humana.
La diabetes es una enfermedad crónica con hiperglucemia como signo principal. Es causada principalmente por una disminución en la secreción de insulina causada por una disfunción de las células de los islotes pancreáticos, o porque el cuerpo es insensible a la acción de la insulina (es decir, resistencia a la insulina), o ambas cosas. la glucosa en la sangre es ineficaz para ser utilizada y almacenada.
El sistema digestivo es uno de los nueve sistemas principales del cuerpo humano y es el principal responsable de la ingesta, digestión, absorción y excreción de los alimentos. Consta de dos partes principales: el tracto digestivo y las glándulas digestivas.
El cáncer de pulmón es un tumor maligno que se origina en la mucosa bronquial o las glándulas de los pulmones. Es uno de los tumores malignos con mayor morbilidad y mortalidad y mayor amenaza para la salud y la vida humana.
La diabetes es una enfermedad crónica con hiperglucemia como signo principal. Es causada principalmente por una disminución en la secreción de insulina causada por una disfunción de las células de los islotes pancreáticos, o porque el cuerpo es insensible a la acción de la insulina (es decir, resistencia a la insulina), o ambas cosas. la glucosa en la sangre es ineficaz para ser utilizada y almacenada.
El sistema digestivo es uno de los nueve sistemas principales del cuerpo humano y es el principal responsable de la ingesta, digestión, absorción y excreción de los alimentos. Consta de dos partes principales: el tracto digestivo y las glándulas digestivas.
Programación concurrente
Modelo de memoria Java (JMM)
Mecanismo de comunicación de hilos.
compartir memoria
Adopción de Java
mensajería
modelo de memoria
Reordenar
Para el desempeño del programa, el procesador y el compilador reordenarán el programa.
condición
Los resultados de la ejecución del programa no se pueden cambiar en un entorno de un solo subproceso.
No se permite reordenar si existen dependencias de datos.
pregunta
Reordenar puede generar datos inseguros en un entorno de subprocesos múltiples
consistencia secuencial
Modelo de referencia teórico en entorno multiproceso.
Proporciona sólidas garantías de visibilidad de la memoria para los programas.
característica
Todas las operaciones en un hilo deben realizarse en el orden del programa.
Todos los subprocesos solo pueden ver un único orden de ejecución de operaciones, independientemente de si el programa está sincronizado o no.
Cada operación debe realizarse de forma atómica e inmediatamente visible para todos los subprocesos.
sucede antes
La teoría central de JMM garantiza la visibilidad de la memoria.
En JMM, si los resultados de una operación deben ser visibles para otra operación, entonces debe haber una relación de ocurre antes entre las dos operaciones.
teoría
Si una operación ocurre antes de otra, entonces los resultados de la ejecución de la primera operación serán visibles para la segunda operación, y el orden de ejecución de la primera operación será anterior a la segunda operación.
La existencia de una relación de "sucede antes" entre dos operaciones no significa que deban ejecutarse en el orden especificado por el principio de "sucede antes". Si el resultado de la ejecución después del reordenamiento es consistente con el resultado de la ejecución según la relación sucede antes, entonces este reordenamiento no es ilegal.
como en serie
Todas las operaciones se pueden reordenar para su optimización, pero debe asegurarse de que los resultados del reordenamiento no se puedan cambiar.
sincronizado
Sincronización, bloqueo pesado
principio
sincronizado puede garantizar que cuando se ejecuta un método o bloque de código, solo un método pueda ingresar a la sección crítica al mismo tiempo. También puede garantizar la visibilidad de la memoria de las variables compartidas.
bloquear objeto
Método de sincronización ordinario, el bloqueo es el objeto de instancia actual
Método de sincronización estática, el bloqueo es el objeto de clase de la clase actual
Bloque de método sincronizado, el candado es el objeto dentro de los corchetes
Mecanismo de implementación
encabezado de objeto Java
El bloqueo sincronizado se almacena en el encabezado del objeto Java.
Incluye dos partes de datos.
Marcar palabra (campo de marca)
Mark Word está diseñado como una estructura de datos no fija para almacenar la mayor cantidad de datos posible en un espacio muy pequeño. Reutilizará su propio espacio de almacenamiento según el estado del objeto.
incluir
Código hash (HashCode), edad de generación de GC, indicador de estado de bloqueo, bloqueo retenido por subproceso, ID de subproceso sesgado, marca de tiempo sesgada
Puntero Klass (tipo puntero)
monitor
Dueño
Inicialmente, NULL significa que ningún subproceso posee actualmente el registro del monitor. Cuando el subproceso posee exitosamente el bloqueo, el identificador único del subproceso se guarda. Cuando se libera el bloqueo, se establece en NULL.
Optimización de bloqueo
bloqueo de giro
El hilo espera un período de tiempo y no se suspenderá inmediatamente para ver si el hilo que mantiene el bloqueo lo liberará pronto (método cíclico)
El número de palabras giratorias es difícil de controlar (-XX:preBlockSpin)
Teoría existencial: los subprocesos con frecuencia se suspenden y se despiertan con una gran carga. Se puede considerar que cada subproceso mantiene el bloqueo por un corto tiempo y la ganancia supera la ganancia después de que el subproceso se suspende y luego se activa.
defecto
No se puede determinar el número de giros.
bloqueo de giro adaptativo
El número de giros ya no es fijo. Está determinado por el tiempo de giro anterior en el mismo candado y el estado del propietario del candado.
Si el giro tiene éxito, se puede aumentar el número de giros. Si la adquisición del candado falla con frecuencia, el número de giros se reducirá.
eliminación de bloqueo
Si no hay competencia de datos, la JVM eliminará el mecanismo de bloqueo.
Juicios basados
escape variable
rugosidad de la cerradura
Conecte varias operaciones consecutivas de bloqueo y desbloqueo para expandirse a una cerradura más grande. Por ejemplo, adquirir un candado dentro de un bucle for.
cerradura ligera
Reduzca el consumo de rendimiento causado por los bloqueos tradicionales pesados utilizando mutexes del sistema operativo sin competencia de subprocesos múltiples.
Adquirir y liberar bloqueos a través de CAS
base de desempeño
Para la mayoría de las cerraduras, no habrá competencia durante todo el ciclo de vida.
defecto
En un entorno de subprocesos múltiples, su eficiencia operativa es más lenta que la de las cerraduras pesadas.
bloqueo de polarización
Para minimizar rutas de ejecución de bloqueos livianos innecesarios sin competencia de subprocesos múltiples
Principalmente evite operaciones CAS innecesarias tanto como sea posible. Si el candado de competencia falla, actualice a un candado liviano.
volátil
característica
Visibilidad volátil: al leer un volátil, siempre puede ver la escritura final en esta variable.
atomicidad volátil: volátil es atómico para una sola lectura/escritura (32 bits de largo, doble), excepto para operaciones compuestas, como i;
Mecanismo de implementación
barrera de la memoria
semántica de la memoria
Al escribir una variable volátil, JMM actualizará inmediatamente el valor de la variable compartida en la memoria local correspondiente al hilo en la memoria principal.
Al leer una variable volátil, JMM configurará la memoria local correspondiente al hilo como no válida y leerá la variable compartida directamente desde la memoria principal.
semántica del sistema operativo
¿La memoria principal y la caché (subproceso privado) son consistentes?
solución
Agregando LOCK# al autobús
A través del protocolo de coherencia de caché (protocolo MESI)
modelo de memoria
Reordenar
sucede antes
DCL
Patrón singleton
DCL
Reordenar
sucede antes
solución
solución volátil
Deshabilitar reordenamiento
Solución basada en la inicialización de clases.
Utilice el mecanismo del cargador de clases para asegurarse de que solo haya un subproceso al inicializar la instancia. La JVM adquirirá un bloqueo durante la fase de inicialización de la clase. Este bloqueo puede sincronizar la inicialización de la misma clase por varios subprocesos.
Conceptos básicos de concurrencia
AQS
AbstractQueuedSynchronizer, sincronizador, implementa los componentes básicos centrales de JUC
Se resolvió una gran cantidad de problemas detallados relacionados con la implementación de sincronizadores en subclases, como la obtención del estado de sincronización y la cola de sincronización FIFO.
Utilizando el patrón de método de plantilla, AQS implementa una gran cantidad de métodos comunes y las subclases implementan sus métodos abstractos a través de la herencia para administrar el estado de sincronización.
Cola de sincronización CLH
Cola bidireccional FIFO, AQS confía en ella para resolver el problema de gestión del estado de sincronización
El primer nodo se activa y espera a que la cola se agregue al final de la cola de sincronización CLH.
Adquisición y liberación de estado sincrónico.
Exclusivo
obtener bloqueo
Obtener estado de sincronización: adquirir
Adquirir Interrumpiblemente: adquirir Interrumpiblemente
Adquisición de tiempo de espera: tryAcquireNanos
desbloquear bloqueo
liberar
compartido
obtener bloqueo
adquirircompartido
desbloquear bloqueo
lanzamientoCompartido
Bloqueo de hilos y despertar
Cuando un subproceso adquiere el bloqueo, otros subprocesos deben bloquearse cuando lo adquieren nuevamente. Cuando el subproceso libera el bloqueo, AQS es responsable de activar el subproceso.
BloqueoSoporte
¿Se utiliza la primitiva básica de bloqueo de subprocesos para crear bloqueos y otras clases de sincronización?
Cada hilo que usa LockSupport está asociado con un permiso. Si el permiso está disponible y se puede usar en el proceso, llamar a park() regresará inmediatamente; de lo contrario, puede bloquearse. Si la licencia aún no está disponible, puede llamar a unpark para que esté disponible
aparcar(), desestacionar()
CAS
Comparar e intercambiar, la teoría central y más básica de todo el sistema JUC
Valor de memoria V, antiguo valor esperado A y valor a actualizar B. Si y solo si el valor del valor de memoria V es igual al antiguo valor esperado A, el valor del valor de memoria V se modificará a B; de lo contrario, no se modificará nada. estar hecho.
Hay cuatro parámetros en nativo.
defecto
Tiempo de ciclo demasiado largo
Solo se puede garantizar que una variable compartida sea operada atómicamente
problema ABA
solución
número de versión
Referencia Atómica Estampada
Cerrar
Bloqueo reentrante
El bloqueo reentrante es un mecanismo de sincronización recursivo sin bloqueo
Un mecanismo de bloqueo más potente y flexible que el sincronizado, que puede reducir la probabilidad de un punto muerto.
Dividido en bloqueo justo y bloqueo injusto.
La capa inferior se implementa utilizando AQS y hereda AQS a través de sincronización interna.
Bloqueo de lectura y escritura reentrante
Bloqueo de lectura y escritura, dos bloqueos: bloqueo compartido: bloqueo de lectura, bloqueo exclusivo: bloqueo de escritura
Admite equidad, injusticia, reentrada y degradación de bloqueos.
Reducción de bloqueo: según el orden en que se adquiere el bloqueo de escritura, se adquiere el bloqueo de lectura y se libera el bloqueo de escritura, el bloqueo de escritura se puede degradar a bloqueo de lectura.
Condición
Lock proporciona Condición, que es más detallada y flexible para las operaciones de activación y espera de subprocesos.
Internamente se mantiene una cola de condiciones. Cuando el hilo actual llama al método await (), se construirá un nodo (Nodo) a partir del hilo actual y el nodo se agregará al final de la cola.
Herramientas de concurrencia
Barrera cíclica
Permite que un grupo de subprocesos se esperen unos a otros hasta que se alcance un punto de barrera común.
En términos sencillos: deje que un grupo de subprocesos se bloquee cuando alcancen una barrera. La barrera no se abrirá hasta que el último subproceso llegue a la barrera y todos los subprocesos interceptados por la barrera continuarán funcionando.
La capa inferior se implementa usando la condición ReentrantLock
Escenarios de aplicación
La operación de fusionar resultados de subprocesos múltiples se utiliza para calcular datos en múltiples subprocesos y finalmente fusionar los resultados del cálculo.
cuenta atrás
Permite que uno o más subprocesos esperen hasta que se complete un conjunto de operaciones que se realizan en otros subprocesos.
Inicializa CountDownLatch con el recuento dado. Debido a que se llama al método countDown(), el método de espera se bloquea hasta que el recuento actual llega a cero. Luego, todos los subprocesos en espera se liberan y todas las llamadas posteriores en espera regresan inmediatamente. Este comportamiento sólo ocurre una vez; el recuento no se puede restablecer. Si necesita restablecer el recuento, considere utilizar un CyclicBarrier.
Diferencia con CyclicBarrier
La función de CountDownLatch es permitir que 1 o N subprocesos esperen a que otros subprocesos completen la ejecución, mientras que CyclicBarrier permite que N subprocesos se esperen entre sí;
El contador de CountDownLatch no se puede restablecer; el contador de CyclicBarrier se puede restablecer y utilizar, por lo que se denomina barrera cíclica.
Implementado internamente mediante bloqueos compartidos.
Semáforo
señal
Un contador que controla el acceso a múltiples recursos compartidos.
Conceptualmente, un semáforo mantiene un conjunto de permisos. Si es necesario, cada adquisición() se bloquea hasta que el permiso esté disponible y luego adquiere el permiso. Cada lanzamiento() agrega un permiso, lo que potencialmente libera un captador de bloqueo. Sin embargo, en lugar de utilizar el objeto de licencia real, Semaphore simplemente cuenta la cantidad de licencias disponibles y toma las medidas correspondientes.
El semáforo Semáforo es un número entero no negativo (>=1). Cuando un hilo quiere acceder a un recurso compartido, primero debe obtener el Semaphore. Cuando Semaphore > 0, obtenga el recurso y establezca Semaphore - 1. Si el valor del semáforo = 0, significa que todos los recursos compartidos han sido ocupados por otros subprocesos y el subproceso debe esperar a que otros subprocesos liberen los recursos. Cuando el hilo libera el recurso, el semáforo es 1
Escenarios de aplicación
A menudo se usa para limitar la cantidad de subprocesos que pueden acceder a ciertos recursos (físicos o lógicos)
Implementado internamente mediante bloqueos compartidos.
Intercambiador
Un punto de sincronización para subprocesos que pueden emparejar e intercambiar elementos en un par.
Permite el intercambio de datos entre tareas simultáneas. Específicamente, la clase Exchanger permite definir puntos de sincronización entre dos subprocesos. Cuando ambos subprocesos alcanzan el punto de sincronización, intercambian estructuras de datos, por lo que la estructura de datos del primer subproceso pasa al segundo subproceso y la estructura de datos del segundo subproceso pasa al primer subproceso.
otro
Hilo local
Una solución al problema de las variables miembro en un entorno multiproceso, pero no tiene nada que ver con la sincronización de subprocesos. La idea es crear una copia separada de la variable para cada hilo, de modo que cada hilo pueda cambiar de forma independiente su propia copia de la variable sin afectar las copias correspondientes de otros hilos.
ThreadLocal no se utiliza para resolver el problema de las variables compartidas, ni existe para coordinar la sincronización de subprocesos, sino que es un mecanismo introducido para facilitar que cada subproceso maneje su propio estado.
cuatro metodos
get(): Devuelve el valor en la copia del hilo actual de esta variable local del hilo
inicialValue(): Devuelve el "valor inicial" del hilo actual para esta variable local de hilo
remove(): Elimina el valor de esta variable local del hilo en el hilo actual
set (valor T): establece el valor en la copia del subproceso actual de esta variable local del subproceso al valor especificado
HiloMapa local
La clave para implementar el mecanismo de aislamiento de subprocesos.
Cada Thread tiene una variable miembro de tipo ThreadLocal.ThreadLocalMap en su interior, que se utiliza para almacenar una copia de la variable ThreadLocal real.
Proporciona un método para almacenar una copia de las variables de cada subproceso utilizando pares clave-valor. La clave es el objeto ThreadLocal actual y el valor es la copia de la variable del subproceso correspondiente.
ten cuidado
La instancia ThreadLocal en sí no almacena un valor, solo proporciona una clave para encontrar una copia del valor en el hilo actual.
Es ThreadLocal contenido en Thread, no Thread contenido en ThreadLocal
problema de pérdida de memoria
HiloMapa local
La clave es un valor de referencia débil. Es una referencia fuerte y no se puede reciclar.
Llamar explícitamente a remove()
Bifurcar/Unir
Un marco para ejecutar tareas en paralelo es un marco que divide tareas grandes en varias tareas pequeñas y finalmente agrega los resultados de cada tarea pequeña para obtener los resultados de la tarea grande.
Idea principal
"Dividir"
fork descompone tareas y join recopila datos
robo de empleo
Un hilo roba tareas de otras colas para su ejecución
El hilo que ejecuta el bloque ayuda al hilo lento a ejecutar la tarea y mejora la eficiencia de toda la tarea.
La cola debe utilizar una cola bidireccional.
clase básica
TenedorJoinPool
Grupo de subprocesos para ejecutar tareas.
TenedorJoinTask
Representa tareas, abstracción de tareas para ForkJoinPool
TenedorJoinWorkerThread
Hilo de trabajo que realiza tareas.
Colecciones concurrentes de Java
Mapa de hash concurrente
CAS sincronizado para garantizar la seguridad de las actualizaciones simultáneas, la capa inferior utiliza una estructura de almacenamiento de lista vinculada de matriz/árbol rojo-negro
Clases internas importantes
Nodo
par clave-valor clave-valor
Nodo de árbol
Nodo de árbol rojo-negro
ÁrbolBin
Es equivalente a un árbol rojo-negro. Su método de construcción es en realidad el proceso de construir un árbol rojo-negro.
Nodo de reenvío
Nodo auxiliar, utilizado para la operación de expansión de ConcurrentHashMap
tamañoCtl
Identificador de control, utilizado para controlar las operaciones de inicialización y expansión de la tabla.
significado
Un número negativo indica que hay operaciones de inicialización o expansión en curso.
-1 significa inicializar
-N indica que hay N-1 subprocesos en operaciones de expansión
Un número positivo o 0 indica que la tabla hash no se ha inicializado. Este valor indica el tamaño de la inicialización o la próxima expansión.
Operaciones importantes
tabla de inicio
Método de inicialización de ConcurrentHashMap
Solo un hilo puede participar en el proceso de inicialización, otros hilos deben suspenderse
El constructor no realiza el proceso de inicialización. En realidad, la inicialización la activa la operación de colocación.
paso
sizeCtl < 0 significa que la inicialización está en progreso y el hilo está suspendido
El hilo obtiene la calificación de inicialización (CAS(SIZECTL, sc, -1)) para realizar el proceso de inicialización.
Una vez completado el paso de inicialización, establezca sizeCtl = 0,75 * n (el siguiente umbral de expansión), lo que indica el tamaño de la siguiente expansión.
poner
Idea principal
Calcule la posición del nodo insertado en la tabla según el valor hash. Si la posición está vacía, insértela directamente; de lo contrario, insértela en una lista o árbol vinculado.
La situación real es más complicada.
paso
La tabla es nula y el subproceso ingresa al paso de inicialización. Si otros subprocesos se están inicializando, el subproceso se bloquea.
Si la posición i actual insertada es nula, significa que esta posición se inserta por primera vez. Simplemente use CAS para insertar el nodo. Si la inserción es exitosa, se llama a addCount para determinar si se necesita expansión. Si la inserción falla, continúe haciendo coincidir (girar)
Si el hash del nodo == MOVER (-1), significa que un hilo se está expandiendo y entrará en el proceso de expansión.
En otros casos, los nodos se insertan de acuerdo con la lista vinculada o la estructura de árbol rojo-negro, pero este proceso requiere bloqueo (sincronización)
conseguir
paso
tabla == nulo; devolver nulo
Obtener de la lista vinculada/nodo de árbol rojo-negro
Expansión
Expansión multiproceso
paso
Cree una nextTable cuyo tamaño sea el doble del tamaño original. Este paso se completa en un entorno de un solo subproceso.
Copie el contenido de la tabla original en nextTable. Este paso permite operaciones multiproceso.
El proceso de convertir una lista vinculada en un árbol rojo-negro
El número de elementos en la lista vinculada alcanza el umbral de 8, luego la lista vinculada se convierte en un árbol rojo-negro
Algoritmo de árbol rojo-negro
La diferencia entre 1,8 y 1,7
Cola vinculada concurrente
Una cola ilimitada segura para subprocesos basada en nodos de enlace, que utiliza el principio FIFO para ordenar elementos e implementada internamente mediante el algoritmo CAS.
inmutabilidad
El siguiente del último elemento de la cola es nulo.
Los elementos de todos los nodos no eliminados en la cola no pueden ser nulos y pueden atravesarse desde el nodo principal.
Para eliminar el nodo, en lugar de configurarlo como nulo directamente, primero establezca su campo de elemento en nulo (el iterador omitirá los nodos con un elemento nulo)
Permita que las actualizaciones iniciales y finales se retrasen. ¿Qué significa? Esto significa que la cabeza y la cola no siempre apuntan al primer elemento y al último elemento (se explica más adelante)
Invariancia y variabilidad de la cabeza.
Invariancia y variabilidad de la cola.
Sutileza: CAS se utiliza para completar operaciones de datos al tiempo que permite inconsistencias en la cola, y la consistencia débil se demuestra completamente.
Mapa de lista de saltos concurrente
La tercera estructura de datos clave-valor: SkipList (lista de omisión)
Saltar lista
Estructura de árbol binario equilibrada
La lista de omisión permite que los datos ordenados se distribuyan en una lista vinculada de múltiples capas, utilizando un número aleatorio de 0-1 para determinar si los datos subirán o no, utilizando un algoritmo de "intercambio de espacio por tiempo". Se agrega un puntero de avance a cada nodo y algunos nodos que es imposible involucrar se pueden ignorar al insertar, eliminar y buscar, mejorando así la eficiencia.
característica
Está compuesto por muchas capas de estructura y los niveles se generan aleatoriamente mediante una cierta probabilidad.
Cada nivel es una lista vinculada ordenada. El valor predeterminado es ascendente. También se puede ordenar según el Comparador proporcionado al crear el mapeo, según el constructor utilizado.
La lista vinculada del nivel más bajo (Nivel 1) contiene todos los elementos
Si un elemento aparece en la lista vinculada del Nivel i, también aparecerá en las listas vinculadas debajo del Nivel i.
Cada nodo contiene dos punteros, uno que apunta al siguiente elemento en la misma lista vinculada y otro que apunta al elemento que se encuentra un nivel por debajo.
Buscar, eliminar, agregar
Conjunto de listas de saltos concurrentes
Implementado internamente usando ConcurrentSkipListMap
atómico
clase de tipo básico
Se utiliza para actualizar tipos básicos de forma atómica.
AtómicoBooleano
Tipo booleano de actualización atómica
Entero atómico
Entero de actualización atómica
atómicolargo
Actualización atómica larga
formación
Actualizar un elemento en una matriz de forma atómica
AtomicIntegerArray
Actualización atómica de elementos en una matriz de números enteros.
AtómicoLongArray
Actualización atómica de elementos en una matriz de enteros largos
Matriz de referencia atómica
Actualización atómica de elementos en una matriz de tipo de referencia.
tipo de referencia
Si desea actualizar varias variables de forma atómica, debe utilizar la clase proporcionada por este tipo de referencia de actualización atómica.
Referencia atómica
Actualización atómica de tipos de referencia.
Actualizador de campo de referencia atómica
Actualización atómica de campos en tipos de referencia.
Referencia atómicamarcable
Actualización atómica de tipos de referencia con bits de bandera.
clase de campo
Si solo necesitamos un determinado campo en una determinada clase, entonces necesitamos usar la actualización atómica de la clase de campo.
AtomicIntegerFieldUpdater
Actualizador para actualizar atómicamente campos enteros
Actualizador AtomicLongField
Actualizador para actualizar atómicamente campos largos
Referencia Atómica Estampada
Actualización atómica de tipo de referencia con número de versión.
cola de bloqueo
ArrayBloqueoCola
Una cola de bloqueo limitada FIFO implementada como una matriz
ArrayBlockingQueue está limitado y fijo. El tamaño se confirma durante el constructor. No se admiten cambios después de la confirmación.
La "imparcialidad" no está garantizada en un entorno multiproceso
lograr
Bloqueo reentrante
Condición
Cola de bloqueo vinculada
Cola de bloqueo FIFO ilimitada y basada en enlaces
Cola de bloqueo de prioridad
Cola de bloqueo ilimitada con soporte prioritario
De forma predeterminada, los elementos se ordenan en orden ascendente en orden natural. Puede ordenar los elementos especificando un Comparador.
montón binario
Clasificación
montón máximo
El valor clave del nodo principal siempre es mayor o igual que el valor clave de cualquier nodo secundario.
montón mínimo
El valor clave del nodo principal siempre es menor o igual que el valor clave de cualquier nodo secundario.
La operación de suma "sube" constantemente, mientras que la operación de eliminación "baja" constantemente
lograr
Condición de bloqueo reentrante
montón binario
Cola de retraso
Cola de bloqueo ilimitada que admite la adquisición retrasada de elementos
solicitud
Caché: borra los datos almacenados en caché que han caducado en el caché
Procesamiento de tiempo de espera de tarea
lograr
Condición de bloqueo reentrante
Cola de prioridad ordenada según el tiempo de retardo: PriorityQueue
Interfaz retrasada
Se utiliza para marcar objetos que deben ejecutarse después de un tiempo de retraso determinado.
Esta interfaz requiere que las clases de implementación que la implementan definan un método compareTo que proporcione un orden consistente con el método getDelay de esta interfaz.
Cola síncrona
Una cola de bloqueo sin capacidad
solicitud
Para intercambiar trabajo, el hilo del productor y el hilo del consumidor se sincronizan para entregar cierta información, eventos o tareas.
Difícil de entender, tiene dificultades con Exchanger.
Cola de transferencia vinculada
Cola de bloqueo ilimitada compuesta por una lista vinculada
Equivalente a un superconjunto de ConcurrentLinkedQueue, SynchronousQueue (en modo justo), LinkedBlockingQueues ilimitados, etc.
modo preventivo
Si está disponible, tómalo directamente. Si no, ocupará esta posición hasta que se obtenga o se agote el tiempo o se interrumpa.
LinkedBlockingDeque
Una cola de bloqueo bidireccional compuesta por una lista vinculada
La capacidad es opcional. Puede configurar la capacidad durante la inicialización para evitar una expansión excesiva. Si no se establece, la capacidad predeterminada es Integer.MAX_VALUE.
usar
Patrón de "robo de empleo"
Grupo de subprocesos
beneficio
Reducir el consumo de recursos
Reduzca el costo de creación y destrucción de subprocesos reutilizando los subprocesos creados.
Mejorar la velocidad de respuesta
Cuando llega una tarea, la tarea se puede ejecutar inmediatamente sin esperar a que se cree el hilo.
Mejorar la capacidad de gestión de subprocesos
Asignación, ajuste y monitoreo unificados
Ejecutor
Ejecutores
La clase de fábrica estática proporciona métodos de fábrica estáticos de Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, Callable y otras clases.
ThreadPoolEjecutor
Significado del parámetro
tamaño de grupo central
El número de subprocesos principales en el grupo de subprocesos.
tamaño máximo de piscina
El número máximo de subprocesos permitidos en el grupo de subprocesos.
manteneralivetime
Tiempo de inactividad del hilo
unidad
unidad de keepAliveTime
cola de trabajo
Una cola de bloqueo utilizada para retener tareas en espera de ser ejecutadas.
cola de bloqueo utilizada
ArrayBloqueoCola
Cola de bloqueo vinculada
Cola síncrona
Cola de bloqueo de prioridad
hiloFábrica
Fábrica utilizada para configurar la creación de hilos.
Fábrica de hilos predeterminada
manipulador
RejectedExecutionHandler, estrategia de rechazo del grupo de subprocesos
Clasificación
AbortPolicy: lanza una excepción directamente, política predeterminada
CallerRunsPolicy: utilice el hilo donde se encuentra la persona que llama para ejecutar tareas
DiscardOldestPolicy: descarta la tarea más importante en la cola de bloqueo y ejecuta la tarea actual
DiscardPolicy: descarta la tarea directamente
Clasificación del grupo de subprocesos
nuevoFixedThreadPool
Grupo de subprocesos reutilizable con un número fijo de subprocesos
analizar
corePoolSize es consistente con MaximumPoolSize
Usando una cola "ilimitada" Cola de bloqueo vinculada
tamaño máximo de piscina, keepAliveTime, Controlador de ejecución rechazado inválido
nuevoCachedThreadPool
Ejecutor usando un solo hilo de trabajo
analizar
corePoolSize y MaximumPoolSize se establecen en 1
Utilice LinkedBlockingQueue como WorkersQueue
nuevoSingleThreadExecutor
Un grupo de subprocesos que crea nuevos subprocesos según sea necesario
analizar
corePoolSize se establece en 0
máximoPoolSize se establece en Integer.MAX_VALUE
SynchronousQueue como WorkerQueue
Si el subproceso principal envía tareas más rápido que los subprocesos en las tareas de proceso de MaximumPool, CachedThreadPool continuará creando nuevos subprocesos, lo que puede agotar los recursos de CPU y memoria.
Envío de tareas
Ejecutor.ejecutar()
EjecutorService.submit()
Ejecución de tareas
Proceso de implementación
Ajuste del grupo de subprocesos
Dos modelos
Monitoreo del grupo de subprocesos
ProgramadoThreadPoolExecutor
Heredado de ThreadPoolExecutor
Ejecute la tarea después de un retraso determinado o ejecute la tarea periódicamente
DelayQueue se utiliza internamente para implementarlo y las tareas programadas se colocarán en DelayQueue. DelayQueue encapsula internamente PriorityQueue, que clasifica las ScheduledFutureTasks en la cola.
Futuro
Cálculo asincrónico
Futuro
Proporcionar operaciones
Cancelación de tareas de ejecución.
Consultar si la tarea está completa
Obtener resultados de ejecución de tareas
tarea futura
Implemente la interfaz RunnableFuture, que puede ejecutarse como Runnable o usarse como Future para obtener el valor de retorno de Callable
Implementado internamente basado en AQS