Le contenu de cet article est une introduction détaillée (exemple de code) sur ThreadLocal en Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
ThreadLocal n'est fondamentalement pas utilisé dans le développement de projets, mais les intervieweurs préfèrent poser ce type de questions ; il est donc toujours nécessaire de comprendre les fonctions et les principes de ce type.
Qu'est-ce que ThreadLocal
🎜>
ThreadLocal est une classe qui créera une copie distincte des variables pour chaque thread dans plusieurs threads ; lors de l'utilisation de ThreadLocal pour conserver les variables, ThreadLocal créera une copie distincte des variables pour chaque thread afin d'éviter l'incohérence des données causée par plusieurs -fonctionnement threadé des variables partagées ;Dans quels scénarios la classe ThreadLocal est-elle utilisée ?ThreadLocal
De manière générale, Scope
n'est pas courant dans la production industrielle réelle, mais dans Il est utilisé dans de nombreux cadres mais peut résoudre certains problèmes de framework ; par exemple, les transactions dans Spring et la portée Request的Bean
dans Spring sont résolues en utilisant ThreadLocal pour
1. pour définir les attributs auxquels plusieurs threads doivent accéder ; prenez comme exemple la classe DBConnectionFactory la plus couramment utilisée sur Internet
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBConnectionFactory { private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() { @Override protected Connection initialValue() { try { return DriverManager.getConnection("", "", ""); } catch (SQLException e) { e.printStackTrace(); } return null; } }; public Connection getConnection() { return dbConnectionLocal.get(); } }
De cette façon, lorsque le client obtient la connexion, chaque thread obtient la connexion Ils sont tous uniques à ce fil, réalisant l'isolation des threads de la connexion ; il n'y a donc pas de problème de sécurité des threads
En utilisant principalement l'un des objets Thread. La variable threadLocals de type ThreadLocalMap est responsable du stockage de l'objet Connection du thread actuel. La variable dbConnectionLocal est utilisée comme clé, et l'objet Connection nouvellement créé est utilisé comme valeur dans ce cas, si le thread n'existe pas lorsque ; elle est lue pour la première fois, ThreadLocal sera appelée. La méthode initialValue crée un objet Connection et renvoie
Le code spécifique pour allouer une copie de la variable au thread est le suivant :
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
1. Obtenez d'abord l'objet thread actuel t, puis obtenez-le à partir du thread t Accédez à l'attribut membre threadLocals
de ThreadLocalMap 2. Si les threadLocals du thread actuel ont été initialisés. (c'est-à-dire non nul) et il y a une valeur avec l'objet ThreadLocal actuel comme clé, renvoie directement l'objet à obtenir par le thread actuel (dans cet exemple (Connexion dans la carte threadLocals du thread, et renvoie
4. Si l'attribut threadLocals du thread actuel n'a pas été initialisé, recréez un objet ThreadLocalMap, créez un objet Connection et ajoutez-le à l'objet ThreadLocalMap et revenez.
S'il existe, il sera renvoyé directement. C'est facile à comprendre. Alors, quel est le code pour initialiser ?
1. Appelez d'abord la méthode initialValue surchargée. a écrit ci-dessus, générez un objet Connectionprivate T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; }
2. Continuez à vérifier si les threadLocals du thread actuel sont vides. Si le ThreadLocalMap a été initialisé, ajoutez directement l'objet généré au ThreadLocalMap. initialisé, créez et ajoutez-y l'objet.
En même temps, ThreadLocal fournit également une méthode pour faire fonctionner directement threadLocals dans l'objet Thread
De cette façon, nous pouvons ne pas non plus implémenter initialValue et mettre le travail d'initialisation dans la méthode getConnection de DBConnectionFactory Medium :public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }Ensuite, après avoir lu le code, nous comprenons clairement pourquoi ThreadLocal peut en fait réaliser une isolation multi-thread des variables ; il utilise la structure de données Map pour mettre en cache le thread actuel. Pour l'utiliser, récupérez-le simplement à partir de l'objet threadLocals de ce thread.
public Connection getConnection() { Connection connection = dbConnectionLocal.get(); if (connection == null) { try { connection = DriverManager.getConnection("", "", ""); dbConnectionLocal.set(connection); } catch (SQLException e) { e.printStackTrace(); } } return connection; }
Bien sûr, si vous récupérez les objets dans la Map ; le thread actuel et les exploiter sous le thread actuel, il n'y aura certainement aucun problème de concurrence de thread. Bien sûr, les variables peuvent être isolées entre les threads ;
Maintenant que nous savons ce qu'est ThreadLocal et comment utiliser ThreadLocal et. ses principes de base de mise en œuvre, pouvons-nous y mettre fin ? En fait, il y a encore une question : quel objet est ThreadLocalMap et pourquoi devrions-nous utiliser cet objet ?
Qu'est-ce que l'objet ThreadLocalMap
1 Il n'implémente pas l'interface Map
2. la plupart, il a un constructeur par défaut, car cette méthode ThreadLocalMap n'est appelée que dans la classe ThreadLocal et appartient à la classe interne statique
3. L'implémentation Entry de ThreadLocalMap hérite de WeakReference
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!