Maison  >  Article  >  Java  >  Introduction détaillée à ThreadLocal en Java (exemple de code)

Introduction détaillée à ThreadLocal en Java (exemple de code)

不言
不言avant
2019-03-06 15:56:283390parcourir

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 ?

ThreadLocalDe 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

Méthode d'utilisation de ThreadLocal

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

Comment ThreadLocal implémente l'isolation 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 Connection
private 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

Essentiellement parlant, c'est une Map, mais ce ThreadLocalMap est différent de la Map que nous voyons habituellement. Un peu différent

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>

4. Cette méthode utilise uniquement un tableau Entry pour stocker la clé, la valeur n'est pas sous la forme d'une liste chaînée, mais une seule entrée est placée dans chaque compartiment

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer