Maison Java javaDidacticiel Que sont les variables locales de thread ?

Que sont les variables locales de thread ?

Jul 21, 2017 pm 02:34 PM

Le nom le plus précis de ThreadLocal traduit en chinois devrait être : variable locale de thread.

A quoi sert cette chose, ou pourquoi existe-t-il une telle chose ? Laissez-moi d'abord vous expliquer que lors de la programmation simultanée, les variables membres sont en fait dangereuses pour les threads si aucun traitement n'est effectué. Chaque thread exploite la même variable, ce qui n'est évidemment pas possible, et nous savons également que le mot-clé volatile ne garantit pas la sécurité des threads. Sûr. Ainsi, dans un cas, nous devons remplir une telle condition : la variable est la même, mais chaque thread utilise la même valeur initiale, c'est-à-dire utilise une nouvelle copie de la même variable. Dans ce cas, ThreadLocal est très utile. Par exemple, la connexion à la base de données de DAO. Nous savons que DAO est un singleton, donc son attribut Connection n'est pas une variable thread-safe. Et chacun de nos threads doit l'utiliser, et chacun utilise le sien. Dans ce cas, ThreadLocal résout mieux ce problème.

Nous analysons ce problème du point de vue du code source.

Définissez d'abord un ThreadLocal :

   ThreadLocal<Connection> tl =  ThreadLocal<Connection>  Connection initConn = = DriverManager.getConnection("url, name and password"=( ==
Copier après la connexion

package java.lang;import java.lang.ref.*;import java.util.concurrent.atomic.AtomicInteger;public class ThreadLocal<T> {   private final int threadLocalHashCode = nextHashCode();   private static AtomicInteger nextHashCode =new AtomicInteger();private static final int HASH_INCREMENT = 0x61c88647;private static int nextHashCode() {return nextHashCode.getAndAdd(HASH_INCREMENT);
    }protected T initialValue() {return null;
    }public ThreadLocal() {
    }public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T)e.value;
        }return setInitialValue();
    }private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);if (map != null)
            map.set(this, value);elsecreateMap(t, value);return value;
    }public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);if (map != null)
            map.set(this, value);elsecreateMap(t, value);
    } public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());         if (m != null)
             m.remove(this);
     }ThreadLocalMap getMap(Thread t) {return t.threadLocals;
    }void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {return new ThreadLocalMap(parentMap);
    }T childValue(T parentValue) {throw new UnsupportedOperationException();
    }static class ThreadLocalMap {static class Entry extends WeakReference<ThreadLocal> {/** The value associated with this ThreadLocal. */Object value;

            Entry(ThreadLocal k, Object v) {super(k);
                value = v;
            }
        }private static final int INITIAL_CAPACITY = 16;private Entry[] table;private int size = 0;private int threshold; // Default to 0private void setThreshold(int len) {
            threshold = len * 2 / 3;
        }private static int nextIndex(int i, int len) {return ((i + 1 < len) ? i + 1 : 0);
        }private static int prevIndex(int i, int len) {return ((i - 1 >= 0) ? i - 1 : len - 1);
        }ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }private ThreadLocalMap(ThreadLocalMap parentMap) {
            Entry[] parentTable = parentMap.table;int len = parentTable.length;
            setThreshold(len);
            table = new Entry[len];for (int j = 0; j < len; j++) {
                Entry e = parentTable[j];if (e != null) {
                    ThreadLocal key = e.get();if (key != null) {
                        Object value = key.childValue(e.value);
                        Entry c = new Entry(key, value);int h = key.threadLocalHashCode & (len - 1);while (table[h] != null)
                            h = nextIndex(h, len);
                        table[h] = c;
                        size++;
                    }
                }
            }
        }private Entry getEntry(ThreadLocal key) {int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];if (e != null && e.get() == key)return e;elsereturn getEntryAfterMiss(key, i, e);
        }private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) {
            Entry[] tab = table;int len = tab.length;while (e != null) {
                ThreadLocal k = e.get();if (k == key)return e;if (k == null)
                    expungeStaleEntry(i);elsei = nextIndex(i, len);
                e = tab[i];
            }return null;
        }private void set(ThreadLocal key, Object value) {Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal k = e.get();if (k == key) {
                    e.value = value;return;
                }if (k == null) {
                    replaceStaleEntry(key, value, i);return;
                }
            }

            tab[i] = new Entry(key, value);int sz = ++size;if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }private void remove(ThreadLocal key) {
            Entry[] tab = table;int len = tab.length;int i = key.threadLocalHashCode & (len-1);for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);return;
                }
            }
        }private void replaceStaleEntry(ThreadLocal key, Object value,                                       int staleSlot) {
            Entry[] tab = table;int len = tab.length;
            Entry e;int slotToExpunge = staleSlot;for (int i = prevIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = prevIndex(i, len))if (e.get() == null)
                    slotToExpunge = i;for (int i = nextIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = nextIndex(i, len)) {
                ThreadLocal k = e.get();if (k == key) {
                    e.value = value;

                    tab[i] = tab[staleSlot];
                    tab[staleSlot] = e;if (slotToExpunge == staleSlot)
                        slotToExpunge = i;
                    cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);return;
                }if (k == null && slotToExpunge == staleSlot)
                    slotToExpunge = i;
            }tab[staleSlot].value = null;
            tab[staleSlot] = new Entry(key, value);if (slotToExpunge != staleSlot)
                cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
        }private int expungeStaleEntry(int staleSlot) {
            Entry[] tab = table;int len = tab.length;tab[staleSlot].value = null;
            tab[staleSlot] = null;
            size--;            Entry e;int i;for (i = nextIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = nextIndex(i, len)) {
                ThreadLocal k = e.get();if (k == null) {
                    e.value = null;
                    tab[i] = null;
                    size--;
                } else {int h = k.threadLocalHashCode & (len - 1);if (h != i) {
                        tab[i] = null;while (tab[h] != null)
                            h = nextIndex(h, len);
                        tab[h] = e;
                    }
                }
            }return i;
        }private boolean cleanSomeSlots(int i, int n) {boolean removed = false;
            Entry[] tab = table;int len = tab.length;do {
                i = nextIndex(i, len);
                Entry e = tab[i];if (e != null && e.get() == null) {
                    n = len;
                    removed = true;
                    i = expungeStaleEntry(i);
                }
            } while ( (n >>>= 1) != 0);return removed;
        }private void rehash() {
            expungeStaleEntries();// Use lower threshold for doubling to avoid hysteresisif (size >= threshold - threshold / 4)
                resize();
        }private void resize() {
            Entry[] oldTab = table;int oldLen = oldTab.length;int newLen = oldLen * 2;
            Entry[] newTab = new Entry[newLen];int count = 0;for (int j = 0; j < oldLen; ++j) {
                Entry e = oldTab[j];if (e != null) {
                    ThreadLocal k = e.get();if (k == null) {
                        e.value = null; // Help the GC} else {int h = k.threadLocalHashCode & (newLen - 1);while (newTab[h] != null)
                            h = nextIndex(h, newLen);
                        newTab[h] = e;
                        count++;
                    }
                }
            }

            setThreshold(newLen);
            size = count;
            table = newTab;
        }private void expungeStaleEntries() {
            Entry[] tab = table;int len = tab.length;for (int j = 0; j < len; j++) {
                Entry e = tab[j];if (e != null && e.get() == null)
                    expungeStaleEntry(j);
            }
        }
    }
}
Copier après la connexion

De cette façon, la même connexion est utilisée , mais chaque connexion est nouvelle et une copie de la même connexion.

Alors, quel est le mécanisme de mise en œuvre ?

1. Chaque objet Thread maintient un ThreadLocalMap en interne. Une telle ThreadLocal Map peut stocker plusieurs ThreadLocals

/* ThreadLocal values pertaining to this thread. This map is maintained
 * by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;
Copier après la connexion

2. méthode, récupérez d'abord le thread actuel, puis récupérez l'objet ThreadLocalMap du thread actuel. S'il n'est pas vide, supprimez la valeur de ThreadLocal, sinon initialisez-le. L'initialisation consiste à définir la valeur de initialValue dans ThreadLocal.

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T)e.value;
    }return setInitialValue();
}
Copier après la connexion

3. Lorsque nous appelons la méthode set(), il est très courant de définir la valeur dans ThreadLocal.

4. Résumé : Lorsque nous appelons la méthode get, il y a en fait un ThreadLocal dans chaque thread actuel. Chaque acquisition ou paramètre est une opération sur ThreadLocal et est distinct des autres threads.

5. Scénario d'application : ThreadLocal est le plus approprié lorsque de nombreux threads doivent utiliser le même objet plusieurs fois et que l'objet doit avoir la même valeur d'initialisation.

6. En fait, peu importe ce que je dis, il vaut mieux regarder le code source pour le rendre plus clair. Si vous voulez regarder le code source, cela implique une WeakReference et une Map. Vous devez comprendre ces deux endroits. Ces deux choses sont des références faibles de a.Java, c'est-à-dire que les références encapsulées (référencées) seront détruites. Objet GC, ce threadLocal en tant que clé peut être détruit, mais tant que la classe que nous définissons n'est pas déchargée, la référence forte de tl fera toujours référence à ce ThreadLocal et ne sera jamais supprimée par gc. b. Semblable à HashMap.

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!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Comment déverrouiller tout dans Myrise
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Comment fonctionne le mécanisme de chargement de classe de Java, y compris différents chargeurs de classe et leurs modèles de délégation? Comment fonctionne le mécanisme de chargement de classe de Java, y compris différents chargeurs de classe et leurs modèles de délégation? Mar 17, 2025 pm 05:35 PM

Le chargement de classe de Java implique le chargement, la liaison et l'initialisation des classes à l'aide d'un système hiérarchique avec Bootstrap, Extension et Application Classloaders. Le modèle de délégation parent garantit que les classes de base sont chargées en premier, affectant la classe de classe personnalisée LOA

Comment implémenter la mise en cache à plusieurs niveaux dans les applications Java à l'aide de bibliothèques comme la caféine ou le cache de goyave? Comment implémenter la mise en cache à plusieurs niveaux dans les applications Java à l'aide de bibliothèques comme la caféine ou le cache de goyave? Mar 17, 2025 pm 05:44 PM

L'article examine la mise en œuvre de la mise en cache à plusieurs niveaux en Java à l'aide de la caféine et du cache de goyave pour améliorer les performances de l'application. Il couvre les avantages de configuration, d'intégration et de performance, ainsi que la gestion de la politique de configuration et d'expulsion le meilleur PRA

Comment puis-je utiliser JPA (Java Persistance API) pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux? Comment puis-je utiliser JPA (Java Persistance API) pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux? Mar 17, 2025 pm 05:43 PM

L'article discute de l'utilisation de JPA pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux. Il couvre la configuration, la cartographie des entités et les meilleures pratiques pour optimiser les performances tout en mettant en évidence les pièges potentiels. [159 caractères]

Comment utiliser Maven ou Gradle pour la gestion avancée de projet Java, la création d'automatisation et la résolution de dépendance? Comment utiliser Maven ou Gradle pour la gestion avancée de projet Java, la création d'automatisation et la résolution de dépendance? Mar 17, 2025 pm 05:46 PM

L'article discute de l'utilisation de Maven et Gradle pour la gestion de projet Java, la construction de l'automatisation et la résolution de dépendance, en comparant leurs approches et leurs stratégies d'optimisation.

Mar 17, 2025 pm 05:45 PM

L'article discute de la création et de l'utilisation de bibliothèques Java personnalisées (fichiers JAR) avec un versioning approprié et une gestion des dépendances, à l'aide d'outils comme Maven et Gradle.

See all articles