Galleria mappe mentale Mappa mentale della mappa della conoscenza del sistema simultaneo Java (programmazione simultanea).
Questa è una mappa mentale sulla mappa della conoscenza del sistema di concorrenza Java (programmazione simultanea), inclusa la coda di blocco, le nozioni di base sulla concorrenza, i blocchi, il modello di memoria JAVA e altri aspetti della conoscenza.
Modificato alle 2023-11-06 19:35:07Microbiologia medica, Infezioni batteriche e immunità riassume e organizza i punti di conoscenza per aiutare gli studenti a comprendere e ricordare. Studia in modo più efficiente!
La teoria cinetica dei gas rivela la natura microscopica dei fenomeni termici macroscopici e le leggi dei gas trovando la relazione tra quantità macroscopiche e quantità microscopiche. Dal punto di vista del movimento molecolare, vengono utilizzati metodi statistici per studiare le proprietà macroscopiche e modificare i modelli di movimento termico delle molecole di gas.
Este é um mapa mental sobre uma breve história do tempo. "Uma Breve História do Tempo" é um trabalho científico popular com influência de longo alcance. Ele não apenas introduz os conceitos básicos da cosmologia e da relatividade, mas também discute os buracos negros e a expansão. Do universo. questões científicas de ponta, como inflação e teoria das cordas.
Microbiologia medica, Infezioni batteriche e immunità riassume e organizza i punti di conoscenza per aiutare gli studenti a comprendere e ricordare. Studia in modo più efficiente!
La teoria cinetica dei gas rivela la natura microscopica dei fenomeni termici macroscopici e le leggi dei gas trovando la relazione tra quantità macroscopiche e quantità microscopiche. Dal punto di vista del movimento molecolare, vengono utilizzati metodi statistici per studiare le proprietà macroscopiche e modificare i modelli di movimento termico delle molecole di gas.
Este é um mapa mental sobre uma breve história do tempo. "Uma Breve História do Tempo" é um trabalho científico popular com influência de longo alcance. Ele não apenas introduz os conceitos básicos da cosmologia e da relatividade, mas também discute os buracos negros e a expansão. Do universo. questões científicas de ponta, como inflação e teoria das cordas.
Programmazione simultanea
Modello di memoria Java (JMM)
Meccanismo di comunicazione del thread
condivisione della memoria
Adozione di Java
messaggistica
modello di memoria
Riordina
Per l'esecuzione del programma, il processore e il compilatore riordineranno il programma.
condizione
I risultati dell'esecuzione del programma non possono essere modificati in un ambiente a thread singolo.
Il riordino non è consentito se esistono dipendenze dai dati
domanda
Il riordinamento potrebbe generare dati non sicuri in un ambiente multi-thread
coerenza sequenziale
Modello teorico di riferimento in ambiente multi-thread
Fornisce forti garanzie di visibilità della memoria per i programmi
caratteristica
Tutte le operazioni in un thread devono essere eseguite nell'ordine del programma
Tutti i thread possono vedere solo un singolo ordine di esecuzione delle operazioni, indipendentemente dal fatto che il programma sia sincronizzato o meno
Ogni operazione deve essere eseguita atomicamente e immediatamente visibile a tutti i thread
succede-prima
La teoria fondamentale di JMM garantisce la visibilità della memoria
In JMM, se i risultati di un'operazione devono essere visibili a un'altra operazione, allora deve esistere una relazione "accade prima" tra le due operazioni.
teoria
Se un'operazione avviene prima di un'altra operazione, i risultati dell'esecuzione della prima operazione saranno visibili alla seconda operazione e l'ordine di esecuzione della prima operazione sarà prima della seconda operazione.
L'esistenza di una relazione succede prima tra due operazioni non significa che queste debbano essere eseguite nell'ordine specificato dal principio succede prima. Se il risultato dell'esecuzione dopo il riordino è coerente con il risultato dell'esecuzione secondo la relazione accade prima, allora questo riordino non è illegale.
come se fosse seriale
Tutte le operazioni possono essere riordinate per l'ottimizzazione, ma è necessario assicurarsi che i risultati del riordino non possano essere modificati.
sincronizzato
Sincronizzazione, blocco pesante
principio
sincronizzato può garantire che quando un metodo o un blocco di codice è in esecuzione, solo un metodo alla volta possa entrare nella sezione critica. Può anche garantire la visibilità della memoria delle variabili condivise.
bloccare l'oggetto
Metodo di sincronizzazione ordinario, il blocco è l'oggetto istanza corrente
Metodo di sincronizzazione statico, il lucchetto è l'oggetto della classe corrente
Blocco del metodo sincronizzato, il lucchetto è l'oggetto racchiuso tra parentesi
Meccanismo di implementazione
Intestazione dell'oggetto Java
Il blocco sincronizzato viene memorizzato nell'intestazione dell'oggetto Java.
Include due parti di dati
Segna parola (segna campo)
Mark Word è progettato come una struttura dati non fissa per archiviare quanti più dati possibile in uno spazio molto piccolo. Riutilizzerà il proprio spazio di archiviazione in base allo stato dell'oggetto.
includere
Codice hash (HashCode), età di generazione GC, flag di stato del blocco, blocco mantenuto dal thread, ID thread distorto, timestamp distorto
Klass Pointer (puntatore di tipo)
tenere sotto controllo
Proprietario
Inizialmente NULL significa che nessun thread attualmente possiede il record di monitoraggio. Quando il thread possiede con successo il blocco, l'identificatore univoco del thread viene salvato. Quando il blocco viene rilasciato, viene impostato su NULL.
Blocca l'ottimizzazione
blocco della rotazione
Il thread attende per un periodo di tempo e non verrà sospeso immediatamente per vedere se il thread che detiene il blocco rilascerà presto il blocco (metodo ciclico)
Il numero di parole di rotazione è difficile da controllare (-XX:preBlockSpin)
Teoria esistenziale: i thread spesso si sospendono e si riattivano con un carico pesante. Si può considerare che ciascun thread mantiene il blocco per un breve periodo e il guadagno supera il guadagno dopo che il thread è stato sospeso e quindi riattivato.
discordanza
Non è possibile determinare il numero di giri
blocco rotazione adattivo
Il numero di giri non è più fisso, ma è determinato dal tempo di giro precedente sulla stessa serratura e dallo stato del proprietario della serratura.
Se il lancio ha successo, il numero di giri potrà essere aumentato. Se l'acquisizione della serratura fallisce frequentemente, il numero di giri verrà ridotto.
eliminazione del blocco
Se non c'è concorrenza sui dati, la JVM eliminerà il meccanismo di blocco
Giudizi basati
Fuga variabile
irruvidimento della serratura
Collega più operazioni consecutive di blocco e sblocco per espandersi in una serratura più grande. Ad esempio, acquisire un lock all'interno di un ciclo for
serratura leggera
Riduci il consumo di prestazioni causato dai tradizionali blocchi pesanti utilizzando i mutex del sistema operativo senza concorrenza multi-thread.
Acquisire e rilasciare i lock tramite CAS
base prestazionale
Per la maggior parte delle serrature non ci sarà concorrenza durante l’intero ciclo di vita.
discordanza
In un ambiente multi-thread, la sua efficienza operativa è più lenta di quella dei blocchi pesanti.
blocco del pregiudizio
Al fine di ridurre al minimo i percorsi di esecuzione dei blocchi leggeri e non necessari senza concorrenza multi-thread
Principalmente evitare il più possibile operazioni CAS non necessarie. Se il blocco della competizione fallisce, passare a un blocco leggero.
volatile
caratteristica
Visibilità volatile: durante la lettura di un volatile, puoi sempre vedere la scrittura finale su questa variabile.
atomicità volatile: volatile è atomico per una singola lettura/scrittura (32 bit di lunghezza, doppia), ad eccezione delle operazioni composte, come i;
Meccanismo di implementazione
barriera della memoria
semantica della memoria
Quando si scrive una variabile volatile, JMM aggiornerà immediatamente il valore della variabile condivisa nella memoria locale corrispondente al thread nella memoria principale.
Durante la lettura di una variabile volatile, JMM imposterà la memoria locale corrispondente al thread su non valida e leggerà la variabile condivisa direttamente dalla memoria principale.
semantica del sistema operativo
Memoria principale, cache (thread privata) cache coerente?
soluzione
Aggiungendo LOCK# al bus
Tramite protocollo di coerenza della cache (protocollo MESI)
modello di memoria
Riordina
succede-prima
DCL
Modello singleton
DCL
Riordina
succede-prima
soluzione
soluzione volatile
Disabilita il riordino
Soluzione basata sull'inizializzazione della classe
Utilizza il meccanismo classloder per garantire che sia presente un solo thread durante l'inizializzazione dell'istanza. La JVM acquisirà un blocco durante la fase di inizializzazione della classe. Questo blocco può sincronizzare l'inizializzazione della stessa classe da più thread.
Nozioni di base sulla concorrenza
AQS
AbstractQueuedSynchronizer, sincronizzatore, implementa i componenti di base principali di JUC
Risolti un gran numero di problemi dettagliati coinvolti nell'implementazione dei sincronizzatori nelle sottoclassi, come l'ottenimento dello stato di sincronizzazione e della coda di sincronizzazione FIFO.
Utilizzando il modello di metodo modello, AQS implementa un gran numero di metodi comuni e le sottoclassi implementano i loro metodi astratti tramite ereditarietà per gestire lo stato di sincronizzazione.
Coda di sincronizzazione CLH
Coda bidirezionale FIFO, AQS si affida ad essa per risolvere il problema di gestione dello stato di sincronizzazione
Il primo nodo si sveglia e attende che la coda venga aggiunta alla fine della coda di sincronizzazione CLH.
Acquisizione e rilascio dello stato sincrono
Esclusivo
Ottieni la serratura
Ottieni lo stato della sincronizzazione: acquisisci
Acquisisci in modo interrompibile: acquisisci in modo interrompibile
Acquisizione timeout: tryAcquireNanos
serratura di rilascio
pubblicazione
condiviso
Ottieni la serratura
acquisireShared
serratura di rilascio
rilascioCondiviso
Blocco del thread e risveglio
Quando un thread acquisisce il blocco, gli altri thread devono bloccarsi quando lo acquisiscono nuovamente. Quando il thread rilascia il blocco, AQS è responsabile del risveglio del thread.
LockSupport
È la primitiva di base del blocco dei thread utilizzata per creare blocchi e altre classi di sincronizzazione
Ogni thread che utilizza LockSupport è associato a un'autorizzazione. Se l'autorizzazione è disponibile e può essere utilizzata nel processo, la chiamata a park() verrà restituita immediatamente, altrimenti potrebbe bloccarsi. Se la licenza non è ancora disponibile, puoi chiamare unpark per renderla disponibile
parcheggia(), sbloccaparcheggia()
CAS
Confronta e scambia, la teoria centrale e più basilare dell'intero sistema JUC
Valore di memoria V, vecchio valore atteso A e valore da aggiornare B. Se e solo se il valore del valore di memoria V è uguale al vecchio valore atteso A, il valore del valore di memoria V verrà modificato in B, altrimenti non verrà modificato nulla essere fatto.
Ci sono quattro parametri in nativo
difetto
Tempo di ciclo troppo lungo
Si può garantire che solo una variabile condivisa funzioni atomicamente
Problema dell'ABA
soluzione
numero della versione
AtomicStampedReference
Serratura
ReentrantLock
Il blocco rientrante è un meccanismo di sincronizzazione ricorsivo e non bloccante
Un meccanismo di blocco più potente e flessibile rispetto a quello sincronizzato, che può ridurre la probabilità di stallo.
Diviso in blocco giusto e blocco ingiusto
Il livello inferiore viene implementato utilizzando AQS ed eredita AQS tramite la sincronizzazione interna.
RientranteReadWriteLock
Blocco lettura-scrittura, due blocchi: blocco condiviso: blocco lettura, blocco esclusivo: blocco scrittura
Supporta equità, ingiustizia, rientro e degrado dei blocchi
Downgrade del blocco: in base all'ordine di acquisizione del blocco di scrittura, acquisizione del blocco di lettura e rilascio del blocco di scrittura, il blocco di scrittura può essere declassato a blocco di lettura.
Condizione
Lock fornisce Condition, che è più dettagliato e flessibile per le operazioni di attesa e riattivazione del thread.
Una coda di condizioni viene mantenuta internamente. Quando il thread corrente chiama il metodo wait(), un nodo (Nodo) verrà costruito dal thread corrente e il nodo verrà aggiunto alla fine della coda.
Strumenti di concorrenza
Barriera ciclica
Consente a un gruppo di thread di attendersi l'un l'altro finché non viene raggiunto un punto barriera comune
In parole povere: lascia che un gruppo di thread venga bloccato quando raggiungono una barriera La barriera non si aprirà finché l'ultimo thread non raggiunge la barriera e tutti i thread intercettati dalla barriera continueranno a funzionare.
Il livello inferiore viene implementato utilizzando la condizione ReentrantLock
Scenari applicativi
L'operazione di unione dei risultati multi-thread viene utilizzata per calcolare i dati in più thread e infine unire i risultati del calcolo.
Conteggio alla rovescia
Consente a uno o più thread di attendere fino al completamento di una serie di operazioni eseguite in altri thread.
Inizializza CountDownLatch con il conteggio specificato. Poiché viene chiamato il metodo countDown(), il metodo wait si blocca finché il conteggio corrente non raggiunge lo zero. Successivamente, tutti i thread in attesa vengono rilasciati e tutte le chiamate successive all'attesa vengono restituite immediatamente. Questo comportamento si verifica solo una volta: il conteggio non può essere azzerato. Se è necessario reimpostare il conteggio, prendere in considerazione l'utilizzo di CyclicBarrier.
Differenza da CyclicBarrier
La funzione di CountDownLatch è di consentire a 1 o N thread di attendere il completamento dell'esecuzione di altri thread mentre CyclicBarrier consente a N thread di attendere l'uno con l'altro;
Il contatore di CountDownLatch non può essere ripristinato; il contatore di CyclicBarrier può essere ripristinato e utilizzato, quindi è chiamato barriera ciclica.
Implementato internamente utilizzando blocchi condivisi
Semaforo
segnale
Un contatore che controlla l'accesso a più risorse condivise
Concettualmente, un semaforo mantiene un insieme di permessi. Se necessario, ogni acquire() si blocca finché l'autorizzazione non è disponibile, quindi acquisisce l'autorizzazione. Ogni release() aggiunge un'autorizzazione, rilasciando potenzialmente un getter bloccante. Tuttavia, invece di utilizzare l'oggetto licenza effettivo, Semaphore conta semplicemente il numero di licenze disponibili e agisce di conseguenza
Il semaforo Il semaforo è un numero intero non negativo (>=1). Quando un thread desidera accedere a una risorsa condivisa, deve prima ottenere il semaforo. Quando semaforo > 0, ottenere la risorsa e impostare Semaforo - 1. Se il valore del semaforo = 0, significa che tutte le risorse condivise sono state occupate da altri thread e il thread deve attendere che altri thread rilascino le risorse. Quando il thread rilascia la risorsa, il semaforo è 1
Scenari applicativi
Spesso utilizzato per limitare il numero di thread che possono accedere a determinate risorse (fisiche o logiche)
Implementato internamente utilizzando blocchi condivisi
Scambiatore
Un punto di sincronizzazione per i thread che possono accoppiare e scambiare elementi in una coppia
Consente lo scambio di dati tra attività simultanee. Nello specifico, la classe Exchanger consente di definire punti di sincronizzazione tra due thread. Quando entrambi i thread raggiungono il punto di sincronizzazione, si scambiano strutture dati, quindi la struttura dati del primo thread va nel secondo thread e la struttura dati del secondo thread va nel primo thread
altro
ThreadLocal
Una soluzione al problema delle variabili membro in un ambiente multi-thread, ma non ha nulla a che fare con la sincronizzazione dei thread. L'idea è quella di creare una copia separata della variabile per ogni thread, in modo che ogni thread possa modificare indipendentemente la propria copia della variabile senza influenzare le copie corrispondenti degli altri thread.
ThreadLocal non viene utilizzato per risolvere il problema delle variabili condivise, né esiste per coordinare la sincronizzazione dei thread, ma è un meccanismo introdotto per facilitare a ciascun thread la gestione del proprio stato.
quattro metodi
get(): restituisce il valore nella copia del thread corrente di questa variabile locale del thread
partialValue(): restituisce il "valore iniziale" del thread corrente per questa variabile locale del thread
rimuovi(): rimuove il valore di questa variabile locale del thread nel thread corrente
set(valore T): imposta il valore nella copia del thread corrente di questa variabile locale del thread sul valore specificato
ThreadLocalMap
La chiave per implementare il meccanismo di isolamento del thread
Ogni thread ha al suo interno una variabile membro di tipo ThreadLocal.ThreadLocalMap, che viene utilizzata per archiviare una copia della variabile ThreadLocal effettiva.
Fornisce un metodo per archiviare una copia delle variabili di ogni thread utilizzando coppie chiave-valore. La chiave è l'oggetto ThreadLocal corrente e il valore è la copia variabile del thread corrispondente.
stai attento
L'istanza ThreadLocal in sé non memorizza un valore, fornisce solo una chiave per trovare una copia del valore nel thread corrente.
È ThreadLocal contenuto in Thread, non Thread contenuto in ThreadLocal
problema di perdita di memoria
ThreadLocalMap
la chiave è un valore di riferimento debole è un valore di riferimento forte e non può essere riciclato
Chiama esplicitamente rimuovi()
Biforca/Unisci
Un framework per l'esecuzione di attività in parallelo è un framework che divide compiti grandi in diversi compiti piccoli e infine riassume i risultati di ciascun compito piccolo per ottenere i risultati del compito grande.
idea principale
"Partizione"
fork scompone le attività e join raccoglie i dati
furto di lavoro
Un thread ruba attività da altre code per l'esecuzione
Il thread che esegue il blocco aiuta il thread lento a eseguire l'attività e migliora l'efficienza dell'intera attività.
La coda dovrebbe utilizzare una coda bidirezionale
classe fondamentale
ForkJoinPool
Pool di thread per l'esecuzione di attività
ForkJoinTask
Rappresenta attività, astrazione di attività per ForkJoinPool
ForkJoinWorkerThread
Thread di lavoro che esegue attività
Raccolte simultanee Java
ConcurrentHashMap
CAS Synchronized garantisce la sicurezza degli aggiornamenti simultanei. Il livello inferiore utilizza una struttura di archiviazione con elenco collegato/albero rosso-nero.
Classi interiori importanti
Nodo
coppia chiave-valore
TreeNode
Nodo dell'albero rosso-nero
TreeBin
È equivalente ad un albero rosso-nero. Il suo metodo di costruzione è in realtà il processo di costruzione di un albero rosso-nero.
ForwardingNode
Nodo ausiliario, utilizzato per l'operazione di espansione ConcurrentHashMap
dimensioneCtl
Identificatore di controllo, utilizzato per controllare le operazioni di inizializzazione ed espansione della tabella
Senso
Un numero negativo indica che sono in corso operazioni di inizializzazione o espansione.
-1 significa inizializzazione
-N indica che ci sono N-1 thread sottoposti a operazioni di espansione
Un numero positivo o 0 indica che la tabella hash non è stata inizializzata. Questo valore indica la dimensione dell'inizializzazione o della successiva espansione.
Operazioni importanti
initTable
Metodo di inizializzazione ConcurrentHashMap
Solo un thread può partecipare al processo di inizializzazione, gli altri thread devono essere sospesi
Il costruttore non esegue il processo di inizializzazione L'inizializzazione viene effettivamente attivata dall'operazione put.
fare un passo
sizeCtl < 0 significa che l'inizializzazione è in corso e il thread è sospeso
Il thread ottiene la qualifica di inizializzazione (CAS(SIZECTL, sc, -1)) per eseguire il processo di inizializzazione
Una volta completata la fase di inizializzazione, impostare sizeCtl = 0,75 * n (la soglia di espansione successiva), indicando la dimensione dell'espansione successiva
Mettere
idea principale
Calcola la posizione del nodo inserito nella tabella in base al valore hash Se la posizione è vuota inserirla direttamente, altrimenti inserirla in una lista o albero collegato.
La situazione reale è più complicata
fare un passo
La tabella è nulla e il thread entra nella fase di inizializzazione. Se altri thread sono in fase di inizializzazione, il thread si blocca.
Se la posizione i corrente inserita è nulla, significa che questa posizione viene inserita per la prima volta. Basta usare CAS per inserire il nodo. Se l'inserimento ha esito positivo, viene chiamato addCount per determinare se è necessaria l'espansione. Se l'inserimento fallisce, continua ad abbinare (girare)
Se l'hash del nodo == MOVED (-1), significa che un thread si sta espandendo e entrerà nel processo di espansione.
In altri casi i nodi vengono inseriti secondo la lista concatenata o la struttura ad albero rosso-nero, ma questo processo richiede il blocco (sincronizzato)
Ottenere
fare un passo
tabella==null;restituisce null
Ottieni dall'elenco collegato/nodo dell'albero rosso-nero
Espansione
Espansione multi-thread
fare un passo
Costruisci una nextTable la cui dimensione è doppia rispetto alla dimensione originale. Questo passaggio viene completato in un ambiente a thread singolo.
Copia il contenuto della tabella originale in nextTable. Questo passaggio consente operazioni multi-thread.
Il processo di conversione di un elenco collegato in un albero rosso-nero
Il numero di elementi nell'elenco collegato raggiunge la soglia 8, quindi l'elenco collegato viene convertito in un albero rosso-nero
Algoritmo dell'albero rosso-nero
La differenza tra 1.8 e 1.7
ConcurrentLinkedQueue
Una coda thread-safe illimitata basata su nodi di collegamento, che utilizza il principio FIFO per ordinare gli elementi e implementata internamente utilizzando l'algoritmo CAS
immutabilità
Il successivo dell'ultimo elemento nella coda è nullo
Gli elementi di tutti i nodi non eliminati nella coda non possono essere nulli e possono essere attraversati dal nodo head.
Per eliminare il nodo, invece di impostarlo direttamente su null, impostare prima il campo dell'elemento su null (l'iteratore salterà i nodi con elemento null)
Consenti il ritardo degli aggiornamenti di testa e coda. Cosa significa? Ciò significa che testa e coda non puntano sempre al primo elemento e all'ultimo elemento (spiegato più avanti)
Invarianza e variabilità della testa
Invarianza e variabilità della coda
Sottigliezza: CAS viene utilizzato per completare le operazioni sui dati consentendo al contempo l'incoerenza nella coda e la coerenza debole è completamente dimostrata.
ConcurrentSkipListMap
La terza struttura dati valore-chiave: SkipList (skip list)
SkipList
Struttura ad albero binario bilanciata
Skip list consente di distribuire i dati ordinati in un elenco collegato multistrato, utilizzando un numero casuale 0-1 per determinare se un dato salirà o meno verso l'alto, utilizzando un algoritmo di "scambio di spazio con tempo". Un puntatore in avanti viene aggiunto a ciascun nodo e alcuni nodi che è impossibile coinvolgere possono essere ignorati durante l'inserimento, l'eliminazione e la ricerca, migliorando così l'efficienza.
caratteristica
È composto da molti strati di struttura e i livelli vengono generati casualmente attraverso una certa probabilità.
Ogni livello è un elenco collegato ordinato. L'impostazione predefinita è in ordine crescente. Può anche essere ordinato in base al comparatore fornito durante la creazione della mappatura, a seconda del costruttore utilizzato.
L'elenco collegato di livello più basso (Livello 1) contiene tutti gli elementi
Se un elemento appare nell'elenco collegato del Livello i, apparirà anche negli elenchi collegati sotto il Livello i.
Ogni nodo contiene due puntatori, uno che punta all'elemento successivo nella stessa lista collegata e uno che punta all'elemento al livello inferiore.
Trova, elimina, aggiungi
SetSkipListConcurrent
Implementato internamente utilizzando ConcurrentSkipListMap
atomico
classe di tipo base
Utilizzato per aggiornare atomicamente i tipi di base
AtomicBoolean
Tipo booleano di aggiornamento atomico
AtomicInteger
Intero di aggiornamento atomico
AtomicLong
Aggiornamento atomico lungo
vettore
Aggiorna atomicamente un elemento in un array
AtomicIntegerArray
Aggiornamento atomico degli elementi in un array di numeri interi
AtomicLongArray
Aggiornamento atomico degli elementi in un array intero lungo
AtomicReferenceArray
Aggiornamento atomico degli elementi in una matrice di tipi di riferimento
tipologia di riferimento
Se desideri aggiornare atomicamente più variabili, devi utilizzare la classe fornita da questo tipo di riferimento di aggiornamento atomico.
Riferimento atomico
Aggiornamento atomico dei tipi di riferimento
AtomicReferenceFieldUpdater
Aggiornamento atomico dei campi nei tipi di riferimento
AtomicMarkableReference
Aggiornamento atomico dei tipi di riferimento con bit di flag
Classe sul campo
Se abbiamo bisogno solo di un determinato campo in una determinata classe, allora dobbiamo utilizzare l'aggiornamento atomico della classe del campo
AtomicIntegerFieldUpdater
Programma di aggiornamento per l'aggiornamento atomico dei campi interi
AtomicLongFieldUpdater
Updater per l'aggiornamento atomico dei campi lunghi
AtomicStampedReference
Aggiornamento atomico del tipo di riferimento con il numero di versione
coda di blocco
ArrayBlockingQueue
Una coda di blocco delimitata FIFO implementata come array
ArrayBlockingQueue è limitato e fisso. La dimensione viene confermata durante il costruttore. Le modifiche non sono supportate dopo la conferma.
L'equità non è garantita in un ambiente multi-thread
compiere
ReentrantLock
Condizione
LinkedBlockingQueue
Coda di blocco FIFO illimitata e basata su collegamento
PriorityBlockingQueue
Coda di blocco illimitata con supporto prioritario
Per impostazione predefinita, gli elementi vengono ordinati in ordine crescente in ordine naturale. È possibile ordinare gli elementi specificando un comparatore.
mucchio binario
Classificazione
mucchio massimo
Il valore della chiave del nodo genitore è sempre maggiore o uguale al valore della chiave di qualsiasi nodo figlio
mucchio minimo
Il valore della chiave del nodo genitore è sempre inferiore o uguale al valore della chiave di qualsiasi nodo figlio
L'operazione di aggiunta "si alza" costantemente, mentre l'operazione di eliminazione "cade" costantemente
compiere
Condizione di blocco del rientro
mucchio binario
DelayQueue
Coda di blocco illimitata che supporta l'acquisizione ritardata di elementi
applicazione
Cache: cancella i dati memorizzati nella cache che sono scaduti
Elaborazione del timeout dell'attività
compiere
Condizione di blocco del rientro
Coda prioritaria ordinata in base al tempo di ritardo: PriorityQueue
Interfaccia ritardata
Utilizzato per contrassegnare gli oggetti che devono essere eseguiti dopo un determinato tempo di ritardo
Questa interfaccia richiede che le classi di implementazione che la implementano definiscano un metodo compareTo che fornisca un ordinamento coerente con il metodo getDelay di questa interfaccia.
Coda sincrona
Una coda di blocco senza capacità
applicazione
Per scambiare lavoro, il thread del produttore e il thread del consumatore vengono sincronizzati per fornire determinate informazioni, eventi o attività
Difficile da capire, ha difficoltà con Exchanger
LinkedTransferQueue
Coda di blocco illimitata composta da un elenco collegato
Equivalente a un superset di ConcurrentLinkedQueue, SynchronousQueue (in modalità fiera), LinkedBlockingQueues illimitati e così via.
modalità preventiva
Se è disponibile, prendilo direttamente. In caso contrario, occuperà questa posizione finché non verrà ottenuto, scadrà o verrà interrotto.
LinkedBlockingDeque
Una coda di blocco bidirezionale composta da un elenco collegato
La capacità è facoltativa È possibile impostare la capacità durante l'inizializzazione per impedire un'espansione eccessiva. Se non viene impostata, la capacità predefinita è Integer.MAX_VALUE.
utilizzo
Modello "furto di lavoro".
Gruppo di discussioni
beneficio
Ridurre il consumo di risorse
Riduci il costo di creazione e distruzione dei thread riutilizzando i thread creati
Migliora la velocità di risposta
Quando arriva un'attività, l'attività può essere eseguita immediatamente senza attendere la creazione del thread.
Migliora la gestibilità dei thread
Allocazione, ottimizzazione e monitoraggio unificati
Esecutore
Esecutori
La classe factory statica fornisce metodi factory statici di Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, Callable e altre classi
ThreadPoolExecutor
Significato dei parametri
corePoolSize
Il numero di thread principali nel pool di thread
dimensione massima della piscina
Il numero massimo di thread consentiti nel pool di thread
keepAliveTime
Tempo di inattività del thread
unità
unità di keepAliveTime
workQueue
Una coda di blocco utilizzata per contenere attività in attesa di essere eseguite
coda di blocco utilizzata
ArrayBlockingQueue
LinkedBlockingQueue
Coda sincrona
PriorityBlockingQueue
threadFactory
Factory utilizzata per impostare la creazione del thread
DefaultThreadFactory
gestore
RejectedExecutionHandler, strategia di rifiuto del pool di thread
Classificazione
AbortPolicy: genera direttamente un'eccezione, policy predefinita
CallerRunsPolicy: utilizza il thread in cui si trova il chiamante per eseguire attività
DiscardOldestPolicy: scarta l'attività in primo piano nella coda di blocco ed esegue l'attività corrente
DiscardPolicy: elimina direttamente l'attività
Classificazione del pool di thread
nuovopool di thread fissi
Pool di thread riutilizzabile con un numero fisso di thread
analizzare
corePoolSize è coerente con maximPoolSize
Utilizzando una coda "illimitata". LinkedBlockingQueue
dimensione massima della piscina, keepAliveTime, Gestore dell'esecuzione rifiutata non valido
nuovoPool di thread nella cache
Esecutore che utilizza un singolo thread di lavoro
analizzare
corePoolSize e maximPoolSize sono impostati su 1
Utilizza LinkedBlockingQueue come workerQueue
nuovoSingleThreadExecutor
Un pool di thread che crea nuovi thread in base alle esigenze
analizzare
corePoolSize è impostato su 0
MaximumPoolSize è impostato su Integer.MAX_VALUE
SynchronousQueue come WorkerQueue
Se il thread principale invia attività più velocemente dei thread nelle attività del processo MaximumPool, CachedThreadPool continuerà a creare nuovi thread, che potrebbero esaurire le risorse di CPU e memoria.
Invio attività
Esecutore.esegui()
ExecutorService.submit()
Esecuzione dell'attività
Processo di implementazione
Ottimizzazione del pool di thread
Due modelli
Monitoraggio del pool di thread
ScheduledThreadPoolExecutor
Ereditato da ThreadPoolExecutor
Esegui l'attività dopo un determinato ritardo oppure esegui l'attività periodicamente
DelayQueue viene utilizzato internamente per implementarlo e le attività pianificate vengono inserite in DelayQueue. DelayQueue incapsula internamente PriorityQueue, che ordina gli ScheduledFutureTasks nella coda.
Futuro
Calcolo asincrono
Futuro
Fornire operazioni
Annullamento delle attività di esecuzione
Interroga se l'attività è stata completata
Ottieni i risultati dell'esecuzione delle attività
FutureTask
Implementa l'interfaccia RunnableFuture, che può essere eseguita come Runnable o utilizzata come Future per ottenere il valore restituito da Callable
Implementato internamente sulla base di AQS