Java ThreadLocal viene utilizzato per creare variabili locali al thread. Sappiamo che tutti i threads di un oggetto condividono le sue variabili, quindi la variabile non è sicura per il thread. Possiamo utilizzare la sincronizzazione per la sicurezza del thread ma se vogliamo evitare la sincronizzazione, possiamo utilizzare le variabili ThreadLocal
.
Java ThreadLocal
Ogni thread ha la sua variabile
ThreadLocal
e possono utilizzare i suoi metodi get() e set() per ottenere il valore predefinito o cambiare il suo valore locale al Thread. Le istanze di ThreadLocal sono tipicamente campi privati statici nelle classi che desiderano associare uno stato a un thread.
Esempio di Java ThreadLocal
Ecco un piccolo esempio che mostra l’uso di ThreadLocal in un programma java e dimostra che ogni thread ha la sua copia della variabile ThreadLocal. EsempioThreadLocal.java
package com.journaldev.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
public class ThreadLocalExample implements Runnable{
// SimpleDateFormat non è thread-safe, quindi ne diamo uno ad ogni thread
private static final ThreadLocal formatter = new ThreadLocal(){
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
public static void main(String[] args) throws InterruptedException {
ThreadLocalExample obj = new ThreadLocalExample();
for(int i=0 ; i<10; i++){
Thread t = new Thread(obj, ""+i);
Thread.sleep(new Random().nextInt(1000));
t.start();
}
}
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
//il pattern del formatter è cambiato qui dal thread, ma non risulterà negli altri thread
formatter.set(new SimpleDateFormat());
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
}
}
L’output del programma di esempio java ThreadLocal sopra riportato è:
Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a
Come puoi vedere dall’output, Thread-0 ha cambiato il valore del formatter ma ancora il formatter predefinito del thread-2 è lo stesso del valore inizializzato. Puoi vedere lo stesso modello anche per gli altri thread. Aggiornamento: La classe ThreadLocal è estesa in Java 8 con un nuovo metodo withInitial()
che prende come argomento l’interfaccia funzionale Supplier. Quindi possiamo usare le espressioni lambda per creare facilmente l’istanza ThreadLocal. Ad esempio, la variabile formatter ThreadLocal sopra può essere definita in una riga come segue:
private static final ThreadLocal<SimpleDateFormat> formatter =
ThreadLocal.<SimpleDateFormat>withInitial
(() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});
Se sei nuovo alle funzionalità di Java 8, controlla Java 8 Features e Java 8 Functional Interfaces. Questo è tutto per ThreadLocal nella programmazione Java. Riferimento: API Doc
Source:
https://www.digitalocean.com/community/tutorials/java-threadlocal-example