Quand et comment dois-je utiliser un ThreadLocal variable?
Quand dois-je utiliser un ThreadLocal
variable?
Comment est-il utilisé?
- Si vous utilisez ThreadLocal, ne jamais écrire un wrapper sur elle !!! Chaque développeur qui veut utiliser la variable doit savoir, c'est 'ThreadLocal'
- Si vous êtes explicite, vous pouvez mettre le nom de votre variable, de sorte que c'est elle qui vous faites affaire avec un ThreadLocal valeur, par exemple
RequestUtils.getCurrentRequestThreadLocal()
. Pas dire que c'est très élégant, mais cela provient du fait que ThreadLocal lui-même n'est pas très élégant dans la plupart des cas.
Vous devez vous connecter pour publier un commentaire.
Un possible (et fréquent) d'utiliser, c'est quand vous avez un objet qui n'est pas thread-safe, mais vous voulez éviter de la synchronisation accès à l'objet (je suis à la recherche à vous, SimpleDateFormat). Au lieu de cela, donner à chaque fil sa propre instance de l'objet.
Par exemple:
La Documentation.
SimpleDateFormat
. C'est peut-être préférable d'utiliser un thread-safe alternative. Si vous acceptez que les singletons sont des mauvais alorsThreadLocal
est encore pire.SimpleDateFormat
serait créé, ce qui est un gaspillage. Thread local est beaucoup mieux car il est flexible et mémoire "fuite" est à peine perceptible et peut être géré lorsque le thread est détruit de toute façon. Membre de la variableSimpleDateFormat
est mauvais parce qu'il n'est pas thread-safe!ThreadLocal
?Depuis un
ThreadLocal
est une référence à des données à l'intérieur d'unThread
, vous pouvez vous retrouver avec classloading les fuites lors de l'utilisation deThreadLocal
s dans les serveurs d'applications à l'aide de pools de threads. Vous devez être très prudent au sujet du nettoyage de tous lesThreadLocal
s vousget()
ouset()
à l'aide de laThreadLocal
'sremove()
méthode.Si vous ne nettoyez pas lorsque vous avez terminé, toutes les références qu'il détient pour les classes chargées dans le cadre d'un déployés webapp restera dans la permanent tas et ne sera jamais ordures collectées. Le redéploiement/annulant le déploiement de la webapp ne va pas nettoyer chaque
Thread
de référence de l'de votre webapp de classe(s) depuis leThread
n'est pas quelque chose que possède votre webapp. Chaque déploiement de créer une nouvelle instance de la classe qui ne sera jamais ordures.Vous allez vous retrouver avec de la mémoire exceptions en raison de l'
java.lang.OutOfMemoryError: PermGen space
et après quelques recherches sur google ne sera probablement augmenter-XX:MaxPermSize
au lieu de corriger le bug.Si vous finissez par l'expérience de ces problèmes, vous pouvez déterminer quel thread et de classe est de conserver ces références à l'aide de Eclipse de la Mémoire de l'Analyseur et/ou en suivant Frank Kieviet ' guide de l' et suivi.
Mise à jour: la Re-découverte d' Alex Vasseur entrée de blog de qui m'a aidé à retrouver des
ThreadLocal
questions que j'avais.Thread
utiliseWeakReference<ThreadLocal>
. Ainsi, lorsque l'associéThreadLocal
estgc
'ed, la Carte permettra également d'éliminer les valeurs au cours de la prochaine ressasser.De nombreux cadres de l'utilisation ThreadLocals à maintenir un certain contexte lié à l'thread courant. Par exemple, lorsque la transaction en cours est stocké dans un ThreadLocal, vous n'avez pas besoin de passer en tant que paramètre par le biais de chaque appel de méthode, au cas où quelqu'un en bas de la pile a besoin d'un accès à elle. Les applications Web peuvent stocker des informations sur la demande actuelle et de la session dans un ThreadLocal, de sorte que l'application dispose d'un accès facile pour eux. Avec Guice vous pouvez utiliser ThreadLocals lors de la mise en œuvre de des étendues personnalisées pour l'injection des objets (Guice par défaut de servlet étendues plus probablement les utiliser en tant que bien).
ThreadLocals sont une sorte de variables globales (bien qu'un peu moins mal parce qu'ils sont limités à un seul thread), donc vous devez être prudent lors de leur utilisation afin d'éviter des effets secondaires indésirables et les fuites de mémoire. La conception de votre Api, de sorte que le ThreadLocal valeurs sera toujours automatiquement désactivée lorsqu'ils ne sont plus nécessaires et que la mauvaise utilisation de l'API ne sera pas possible (par exemple comme ceci). ThreadLocals peut être utilisé pour rendre le code plus propre, et dans certains rares cas, ils sont la seule façon de faire quelque chose à travailler (mon projet actuel a deux cas de ce type; ils sont documentés ici sous "les Champs Statiques et Variables Globales").
En Java, si vous avez une donnée qui peut varier par thread, vos choix sont à transmettre cette donnée autour de chaque méthode qui doit (ou peut-être besoin), ou à associer le système de référence avec le fil. En passant le point de référence autour de partout peut être réalisable si tous vos méthodes déjà besoin de passer autour d'un même "contexte" à la variable.
Si ce n'est pas le cas, vous ne voulez pas encombrer votre signatures de méthode avec un paramètre supplémentaire. Dans un non-filetée monde, vous pourriez résoudre le problème avec Java équivalent d'une variable globale. Dans une tige de parole, l'équivalent d'une variable globale est une variable locale de thread.
Il est un très bon exemple dans le livre Java de la Simultanéité dans la Pratique. Où l'auteur (Joshua Bloch) explique comment le Thread de l'accouchement est l'une des façons les plus simples pour parvenir à la sécurité des threads et ThreadLocal est plus formel les moyens de maintenir fil de l'accouchement. À la fin il explique également comment les gens peuvent en abuser en l'utilisant comme variables globales.
J'ai copié le texte du livre susmentionné mais le code 3.10 est absente, tout comme il n'est pas très important de comprendre d'où ThreadLocal, devrait être utilisée.
Essentiellement, lorsque vous avez besoin d'un valeur de la variable à dépendre sur le thread en cours et il n'est pas pratique pour vous de fixer la valeur au fil d'une autre façon (par exemple, sous-classement thread).
Un cas typique est celui où un autre cadre a créé le thread que votre code est en cours d'exécution, par exemple dans un conteneur de servlet, ou l'endroit où il est plus logique d'utiliser ThreadLocal parce que votre variable est alors "dans sa logique" (plutôt qu'une variable suspendu à un Fil sous-classe ou dans certains autres hash map).
Sur mon site web, j'ai quelques autres discussion et des exemples d'utilisation de ThreadLocal qui peut également être d'intérêt.
Certains préconisent l'utilisation de ThreadLocal comme un moyen d'attacher un "ID de thread" à chaque thread dans certains simultanées des algorithmes où vous avez besoin d'un numéro de fil (voir, par exemple, Herlihy & Shavit). Dans ce cas, vérifiez que vous êtes vraiment obtenir un avantage!
ThreadLocal en Java a été introduite sur la JDK 1.2, mais a été plus tard generified dans le JDK 1.5 à introduire le type de sécurité sur ThreadLocal variable.
ThreadLocal peut être associé avec du Fil portée, tout le code qui est exécuté par le Thread a accès à ThreadLocal variables, mais deux thread ne peut pas voir les uns les autres ThreadLocal variable.
Chaque thread détient en exclusivité une copie de ThreadLocal variable qui devient admissible à la collecte des Déchets après que le thread a fini ou est décédé, normalement ou en raison de toute Exception, compte tenu de ces ThreadLocal variable n'a pas d'autres vivent des références.
ThreadLocal variables en Java sont généralement privés de champs statiques dans les Classes et de maintenir son état à l'intérieur du Fil.
Lire la suite: ThreadLocal en Java - Exemple de Programme et un Tutoriel
La documentation dit très bien: "chaque thread accède à [une variable locale de thread] (par l'intermédiaire de son d'obtenir ou de définir la méthode) a son propre, indépendamment initialisé copie de la variable".
Vous utilisez un lors de chaque thread doit avoir sa propre copie de quelque chose. Par défaut, les données sont partagées entre les threads.
Webapp serveur peut maintenir un pool de threads, et un
ThreadLocal
var doit être retiré avant la réponse au client, ainsi thread en cours peuvent être réutilisés par la demande suivante.Deux cas d'utilisation où threadlocal variable peut être utilisée -
1 - Lorsque nous avons une exigence d'associer état avec un filetage (par exemple, un ID d'utilisateur ou ID de Transaction). Que se passe généralement avec une application web que chaque demande d'aller à une servlet a un unique transactionID associés.
Noter qu'ici, la méthode withInitial est mis en œuvre à l'aide d'expressions lambda.
2 - un Autre cas est quand on veut avoir un thread-safe exemple et nous ne voulons pas utiliser la synchronisation que le coût de performances avec la synchronisation est plus. Tel est le cas lorsque SimpleDateFormat est utilisé. Depuis SimpleDateFormat n'est pas thread-safe, donc nous devons fournir un mécanisme pour le faire thread-safe.
Depuis Java 8 release, il n'y a plus déclaratif d'initialiser
ThreadLocal
:Jusqu'à ce que Java 8 release vous deviez effectuer les opérations suivantes:
En outre, si l'instanciation de la méthode (constructeur, méthode de fabrique) de la classe qui est utilisée pour
ThreadLocal
ne prend aucun paramètre, vous pouvez simplement utiliser la méthode des références (introduit dans Java 8):Remarque:
L'évaluation est paresseux puisque vous êtes de passage à
java.util.function.Supplier
lambda qui est évaluée uniquement lorsqueThreadLocal#get
nom, mais la valeur n'a pas été évalué.Vous devez être très prudent avec les ThreadLocal modèle. Il y a quelques grandes sur les côtés, comme Phil mentionné, mais qui n'était pas mentionné est de s'assurer que le code qui définit le ThreadLocal contexte n'est pas "ré-entrant."
De mauvaises choses peuvent se produire lorsque le code qui définit l'information soit exécuter une deuxième ou une troisième fois parce que les informations sur votre fil peut commencer à muter quand vous ne l'attendez pas. Afin de prendre soin de s'assurer que le ThreadLocal l'information n'a pas été mis en avant à nouveau.
ThreadLocal
modèle. Si vous neF(){ member=random(); F2(); write(member); }
et F2 remplace membre avec une nouvelle valeur, puis évidemmentwrite(member)
ne plus écrire le numéro que vous avezrandom()
ed. C'est littéralement juste du bon sens. De même, si vous neF(){ F(); }
, puis gd chance avec votre boucle infinie! C'est vrai partout et n'est pas spécifique àThreadLocal
.quand?
Lorsqu'un objet n'est pas thread-safe, au lieu de synchronisation, ce qui freine l'évolutivité, de donner un objet à tous les fils et de le garder fil portée, ce qui est ThreadLocal. L'un des plus fréquemment utilisé, mais pas thread-safe sont les objets de Connexion de base de données et JMSConnection.
Comment ?
Un exemple est le Printemps framework utilise ThreadLocal fortement pour la gestion des transactions dans les coulisses par le maintien de ces objets de connexion dans ThreadLocal variables. Au plus haut niveau, lorsqu'une transaction est démarrée, il obtient la connexion ( et désactive la validation automatique ) et la maintient dans ThreadLocal. sur la poursuite de la db appels, il utilise la même connexion pour communiquer avec db. À la fin, il prend la connexion de ThreadLocal et s'engage à le ( ou la restauration ) de la transaction et libère la connexion.
Je pense que log4j utilise également ThreadLocal pour le maintien de la MDC.
ThreadLocal
est utile lorsque vous voulez avoir un état qui ne doivent pas être partagés entre les différents threads, mais il devrait être accessible à partir de chaque thread pendant toute sa durée de vie.Comme un exemple, imaginez une application web, où chaque requête est servie par un thread différent. Imaginez que, pour chaque demande, vous avez besoin d'un morceau de données plusieurs fois, ce qui est assez onéreux. Cependant, que les données ont peut être changé pour chaque requête entrante, ce qui signifie que vous ne pouvez pas utiliser un simple cache. Simple, rapide solution à ce problème serait d'avoir un
ThreadLocal
variable contenant de l'accès aux données, de sorte que vous avez à calculer qu'une seule fois pour chaque demande. Bien sûr, ce problème peut également être résolu sans l'utilisation deThreadLocal
, mais je l'a inventé à des fins d'illustration.Cela dit, avoir à l'esprit que
ThreadLocal
s sont essentiellement une forme de l'état global. En conséquence, il a de nombreuses autres implications et doit être utilisé uniquement après avoir examiné toutes les autres solutions possibles.ThreadLocal
comme champ d'objet...ThreadLocal
, où il était accessible dans le monde entier. Comme vous l'avez dit, il peut encore être utilisé comme un champ de classe de limiter la visibilité.Rien de vraiment nouveau ici, mais j'ai découvert aujourd'hui que
ThreadLocal
est très utile lors de l'utilisation de Bean Validation, dans une application web. Les messages de Validation sont localisées, mais par défaut, utilisezLocale.getDefault()
. Vous pouvez configurer leValidator
avec un autreMessageInterpolator
, mais il n'y a aucun moyen de spécifier leLocale
lorsque vous appelezvalidate
. Vous pouvez donc créer un statiqueThreadLocal<Locale>
(ou mieux encore, un conteneur avec d'autres choses que vous pourriez avoir besoin pour êtreThreadLocal
et ensuite votre personnaliséMessageInterpolator
choisir leLocale
de que. La prochaine étape consiste à écrire unServletFilter
qui utilise une valeur de session ourequest.getLocale()
de choisir les paramètres régionaux et de le stocker dans votreThreadLocal
de référence.Comme cela a été mentionné par @inconnu (google), il est d'usage de définir une variable globale dans laquelle la valeur référencée peut être unique dans chaque thread. Il est des usages implique généralement le stockage de certains de tri de l'information contextuelle qui est liée à la thread en cours d'exécution.
Nous l'utilisons dans un environnement Java EE pour transmettre l'identité de l'utilisateur pour les classes qui ne sont pas Java EE connaissance (qui n'ont pas accès à HttpSession, ou de l'EJB SessionContext). De cette façon, le code, ce qui rend l'utilisation de l'identité de la sécurité en fonction des opérations, peut accéder à l'identité de n'importe où, sans avoir à transmettre explicitement dans chaque appel de méthode.
La demande de réponse du cycle d'exploitation dans la plupart des Java EE appels rend ce type d'utilisation facile, car il donne bien défini d'entrée et de sortie des points de définir et de désactiver la ThreadLocal.
Par Définition:
Chaque
Thread
en java contientThreadLocalMap
en elle.Où
La réalisation de la ThreadLocal:
Maintenant créer une classe wrapper pour ThreadLocal qui va contenir la mutable objet comme ci-dessous (avec ou sans
initialValue()
).Maintenant getter et setter de ce wrapper travail sur threadlocal instance au lieu d'mutable objet.
Si getter() de threadlocal n'ai pas trouver une valeur dans le threadlocalmap de la
Thread
; alors qu'il invoquera le initialValue() pour obtenir sa copie privée à l'égard du fil.Maintenant
wrapper.getDateFormatter()
appellerathreadlocal.get()
et qui permettra de vérifier lacurrentThread.threadLocalMap
contient ce (threadlocal) exemple.Si oui, de retour de la valeur (SimpleDateFormat) correspondant threadlocal instance
d'autre ajouter la carte avec cette threadlocal exemple, initialValue().
Ci-joint la sécurité des threads réalisés sur ce mutable classe; par chaque thread est de travailler avec ses propres mutable instance, mais avec le même ThreadLocal instance. Signifie que Tous les threads partagent le même ThreadLocal exemple sous forme de clé, mais différents SimpleDateFormat exemple comme valeur.
https://github.com/skanagavelu/yt.tech/blob/master/src/ThreadLocalTest.java
Ces variables sont souvent utilisés afin d'empêcher le partage de conceptions basées sur
mutable Singletons ou des variables globales.
Il peut être utilisé dans des scénarios tels que la prise de séparer la connexion JDBC pour chaque thread lorsque vous n'êtes pas à l'aide d'un Pool de connexions.
Lorsque vous appelez getConnection, il sera de retour une connexion associée à ce thread.La même chose peut être fait avec d'autres propriétés comme la dateformat, contexte de transaction que vous ne souhaitez pas partager entre les threads.
Vous pouvaient ont aussi utilisé des variables locales pour la même chose, mais ces ressources prennent généralement le temps de la création,de sorte que vous ne souhaitez pas créer encore et encore, chaque fois que vous effectuez une logique métier avec eux. Cependant, ThreadLocal, les valeurs sont stockées dans le thread de l'objet lui-même et dès que le fil est de ces ordures, ces valeurs sont allés trop.
Ce lien explique l'utilisation de ThreadLocal très bien.
La ThreadLocal classe en Java vous permet de créer des variables qui ne peuvent être lus et écrits par le même thread. Ainsi, même si deux threads s'exécutent le même code, et le code a une référence à une ThreadLocal variable, puis les deux threads ne peuvent pas voir les uns les autres ThreadLocal variables.
Lire plus
[De Référence]ThreadLocal ne peut pas résoudre les problèmes de mise à jour de l'objet partagé. Il est recommandé d'utiliser un staticThreadLocal objet qui est partagée par toutes les opérations dans le même thread.
[Obligatoire]méthode remove() doit être mis en œuvre par ThreadLocal variables, en particulier lors de l'utilisation de pools de threads dans lequel les threads sont souvent réutilisés. Sinon, il peut affecter les affaires de la logique et de causer des problèmes inattendus tels que la fuite de mémoire.
La mise en cache, parfois, vous devez calculer la valeur de même beaucoup de temps, donc par le stockage de la dernière série d'entrées d'une méthode et du résultat, vous pouvez accélérer le code. En utilisant Thread Local Storage vous éviter d'avoir à réfléchir sur le verrouillage.
ThreadLocal est spécialement configuré la fonctionnalité de la JVM de fournir un espace de stockage isolé pour les threads seulement. comme la valeur de l'instance d'étendue variable sont liés à une instance d'une classe seulement. chaque objet a ses seules valeurs et qu'ils ne peuvent pas voir les uns les autres de la valeur. donc c'est le concept de ThreadLocal variables, ils sont locaux au fil dans le sens des instances d'objet autre thread à l'exception de celui qui l'a créé, ne peut pas le voir. Voir Ici
Threadlocal fournit un moyen très facile de réaliser des objets de réutilisabilité avec un coût nul.
J'ai eu une situation où plusieurs threads ont été la création d'une image de mutable cache, sur chaque notification de mise à jour.
J'ai utilisé un Threadlocal sur chaque fil, puis chaque thread juste besoin de réinitialiser l'ancienne image et ensuite mettre à jour à partir du cache sur chaque notification de mise à jour.
Habitude d'objets réutilisables à partir de l'objet de réserves de sécurité des threads et des coûts qui leur sont associés, bien que cette approche n'en a aucun.
Il y a 3 scénarios pour l'utilisation d'un classe helper comme SimpleDateFormat en multithread code, qui a le mieux est d'utiliser ThreadLocal
Scénarios
1- en Utilisant comme partager objet par l'aide de de verrouillage de synchronisation ou mécanisme qui rend l'application lent
2- en Utilisant comme objet local à l'intérieur d'une méthode
Dans ce scénario, si nous avons 4 thread chacun appelle une méthode 1000 temps, puis nous avons
4000 SimpleDateFormat objet créé et en attente de GC pour les effacer
3- À L'Aide De ThreadLocal
si nous avons 4 thread et nous avons donné à chaque thread d'un SimpleDateFormat instance
nous avons donc 4 threads, 4 objets de SimpleDateFormat.
Il n'est pas nécessaire de mécanisme de verrouillage et de l'objet de la création et de la destruction. (Bon le temps de la complexité et de l'espace de la complexité)