La classe ThreadLocal peut être comprise comme ThreadLocalVariable (variable locale de thread), qui fournit des interfaces d'accès ou des méthodes telles que get et set. Ces méthodes stockent une copie indépendante pour chaque thread qui utilise la variable, donc get renvoie toujours l'emplacement de l'exécution en cours. thread La dernière valeur définie lors de l’appel de set. ThreadLocal<T> peut être considéré comme contenant un objet Map<Thread,T>, contenant des valeurs spécifiques à ce thread.
En résumé, pour le problème du partage de ressources multi-thread, le mécanisme de synchronisation adopte la méthode « d'échange de temps contre de l'espace », tandis que ThreadLocal adopte la méthode « d'échange d'espace contre du temps ». Le premier fournit uniquement une copie de la variable pour que différents threads puissent accéder en file d'attente, tandis que le second fournit une copie de la variable pour chaque thread, de sorte qu'il soit possible d'y accéder en même temps sans s'affecter mutuellement.
Discussion simuléeLocal
Copiez le code comme suit :
importer java.util.Collections ;
importer java.util.HashMap ;
importer java.util.Map ;
classe publique SimpleThreadLocal<T> {
Private Map<Thread, T> valueMap = Collections
.synchronizedMap(new HashMap<Thread, T>());
public void set (T nouvelle valeur) {
valueMap.put(Thread.currentThread(), newValue); // ①La clé est l'objet thread et la valeur est une copie de la variable de ce thread
}
public T obtenir() {
Thread currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Renvoie la variable correspondant à ce thread
if (o == null && !valueMap.containsKey(currentThread)) { // ③S'il n'existe pas dans la carte, placez-le dans la carte et enregistrez-le.
o = valeurinitiale();
valueMap.put(currentThread, o);
}
revenir o;
}
public void supprimer() {
valueMap.remove(Thread.currentThread());
}
protégé T valeur initiale() {
renvoie null ;
}
}
UtilitaireThreadLocal
Copiez le code comme suit :
nombre de classes {
private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@Outrepasser
Entier protégé valeur initiale() {
renvoie 0 ;
}
} ;
public Integer augmentation() {
count.set(count.get() + 1);
return count.get();
}
}
la classe TestThread implémente Runnable {
compte privé;
public TestThread (nombre de comptes) {
this.count = nombre ;
}
@Outrepasser
public void run() {
// TODO Stub de méthode généré automatiquement
pour (int je = 1; je <= 3; i++) {
System.out.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + count.increase());
}
}
}
classe publique TestThreadLocal {
public static void main (String[] arguments) {
Compte compte = nouveau Compte ();
Thread t1 = nouveau Thread(nouveau TestThread(count));
Thread t2 = nouveau Thread(nouveau TestThread(count));
Thread t3 = nouveau Thread(nouveau TestThread(count));
Thread t4 = nouveau Thread(nouveau TestThread(count));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Le code de copie de sortie est le suivant :
Sujet-0 1e 1
Sujet-0 2e 2
Sujet-0 3ème 3
Fil-3 1e 1
Fil-1 1e 1
Sujet-1 2e 2
Fil-2 1e 1
Sujet-1 3ème 3
Sujet-3 2ème 2
Fil-3 3ème 3
Sujet-2 2e 2
Fil-2 3ème 3