Maison  >  Article  >  Java  >  Quel est le principe d'implémentation des variables de thread ThreadLocal en Java

Quel est le principe d'implémentation des variables de thread ThreadLocal en Java

PHPz
PHPzavant
2023-05-16 21:07:10522parcourir

Qu'est-ce que ThreadLocal ?

ThreadLocal nous permet de créer des variables privées de thread. Cette variable est invisible pour les autres threads. ThreadLocal crée une copie de la variable dans chaque thread, et chaque thread peut accéder à lui-même aux variables de thread privé, l'exemple de code. est la suivante :

public class ThreadLocalDemo {
 
    //创建一个ThreadLocal对象,用来为每个线程会复制保存一份变量,实现线程封闭
    private  static ThreadLocal<Integer> localNum = new ThreadLocal<Integer>(){
        @Override
        protected Integer initialValue() {
            return 1;
        }
    };
 
    public static void main(String[] args) {
          //线程0
          new Thread(){
              @Override
              public void run() {
                   localNum.set(1);
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  localNum.set(localNum.get()+10);
                  System.out.println(Thread.currentThread().getName()+":"+localNum.get());//11
              }
          }.start();
        //线程1
        new Thread(){
            @Override
            public void run() {
                localNum.set(3);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                localNum.set(localNum.get()+20);
                System.out.println(Thread.currentThread().getName()+":"+localNum.get());//23
            }
        }.start();
        
        System.out.println(Thread.currentThread().getName()+":"+localNum.get());//0
    }
}

Comme mentionné ci-dessus, en comptant le thread principal et les deux threads nouvellement créés, il y a trois threads au total. Chaque thread contient sa propre variable privée. Ici, nous définissons la valeur 1, set() et get(. ) sont utilisées pour définir et obtenir des valeurs. Les résultats de l'exécution sont les suivants :

Quel est le principe dimplémentation des variables de thread ThreadLocal en Java

Analyse du principe d'implémentation de ThreadLocal

ThreadLocal est une classe générique qui peut accepter tout type d'objet et maintient une classe interne ThreadLocalMap en interne, les get(), set(), etc. que nous utilisons proviennent en fait de cette classe. Chaque fois qu'un objet ThreadLocalMap est créé pour que le thread actuel enregistre des valeurs privées

Quel est le principe dimplémentation des variables de thread ThreadLocal en Java

Regardons d'abord la méthode set()

public void set(T value) {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程map
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //存在设置值
        map.set(this, value);
    else
        //不存在则创建
        createMap(t, value); 
}
void createMap(Thread t, T firstValue) {
    //threadLocals属性即为此map
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

Ensuite, la méthode get()

public T get() {
    //拿到当前线程
    Thread t = Thread.currentThread();
    //拿到当前线程对应的map
    ThreadLocalMap map = getMap(t);
    //如果已有map
    if (map != null) {
        //取值操作, 拿到对应的Entry
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
           @SuppressWarnings("unchecked")
           T result = (T)e.value;
           return result;
        }
    }
    //没有map, 则去创建初始化一个map
    return setInitialValue();
}
private T setInitialValue() {
    //initialValue()方法返回的value为null
    T value = initialValue();
    //拿到当前线程去创建对应的map
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

ThreadLocal peut être comprise comme un package de ThreadLocalMap

Problème de fuite de mémoire ThreadLocal

Dans ThreadLocalMap, l'objet ThreadLocal utilise des références faibles comme clés

Quel est le principe dimplémentation des variables de thread ThreadLocal en Java

Dans ce cas, si un ThreadLocal cal Lorsqu'il n'y a pas de référence externe forte, alors la clé est destinée à être recyclée par GC, ce qui rend la clé dans ThreadLocalMap nulle et la valeur a toujours une chaîne de référence forte

Un thread peut avoir plusieurs ThreadLocals en même temps time. Si la clé en tant que référence faible est recyclée Après cela, la valeur ne peut pas être recyclée, cela entraînera donc un cycle de vie de ce ThreadLocal aussi long que ce thread (car la chaîne de référence forte de cette valeur ne sera pas rompue). jusqu'à ce que le thread termine son exécution). Si le thread ne se termine jamais, la valeur accumulée n'a pas non plus pu être recyclée, il y aura donc un problème de fuite de mémoire

La façon de résoudre le problème ici est : appelez sa méthode remove(). pour effacer les données à chaque fois après avoir utilisé ThreadLocal

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
       m.remove(this);
}

Jetons un coup d'œil ici à la force et à la faiblesse de la clé. La différence entre les références

Si la clé est utilisée comme référence forte, son cycle de vie est aussi long que le fil. Il existe une chaîne de référence forte et stable et ne peut pas être recyclée, provoquant des fuites de mémoire. Si elle est utilisée comme référence faible, le GC la recyclera automatiquement. Ils peuvent également mieux recycler la valeur dans la méthode Remove() suivante, nous concevons donc généralement. ThreadLocal doit être statique privé et utilisez la méthode remove() pour les supprimer manuellement après utilisation

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