Heim  >  Artikel  >  Java  >  Was ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?

Was ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?

PHPz
PHPznach vorne
2023-05-16 21:07:10565Durchsuche

Was ist ThreadLocal?

ThreadLocal ermöglicht es uns, Thread-private Variablen zu erstellen. Diese Variable ist für andere Threads unsichtbar und jeder Thread kann auf sich selbst zugreifen, das Codebeispiel ist wie folgt:

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
    }
}

Wie oben erwähnt, gibt es mit dem Hauptthread und den beiden neu erstellten Threads insgesamt drei Threads. Hier setzen wir den Wert 1, set () und get(. )-Methoden werden zum Festlegen und Abrufen von Werten verwendet:

Was ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?

ThreadLocal-Implementierungsprinzipanalyse

ThreadLocal ist eine generische Klasse, die jeden Objekttyp akzeptieren kann und intern eine statische ThreadLocalMap verwaltet. Die von uns verwendeten get(), set() usw. stammen tatsächlich aus dieser Klasse. Jedes Mal, wenn ein ThreadLocalMap-Objekt für den aktuellen Thread erstellt wird, um private Werte aufzuzeichnen, schauen wir uns zuerst die set()-Methode an

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); 
}
rrree

Dann gibt es noch die get()-MethodeWas ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?

void createMap(Thread t, T firstValue) {
    //threadLocals属性即为此map
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
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();
}

ThreadLocal kann als Paket von ThreadLocalMap verstanden werden

ThreadLocal-Speicherverlustproblem

In ThreadLocalMap verwendet das ThreadLocal-Objekt schwache Referenzen als Schlüssel

In diesem Fall, wenn a ThreadLocal cal Wenn keine externe starke Referenz vorhanden ist, ist der Schlüssel dazu bestimmt, von GC recycelt zu werden, was dazu führt, dass der Schlüssel in ThreadLocalMap null ist und der Wert immer noch eine starke Referenzkette hat

Ein Thread kann mehrere ThreadLocals haben Gleichzeitig wird der Schlüssel als schwache Referenz recycelt. Danach kann der Wert nicht recycelt werden, sodass der Lebenszyklus dieses ThreadLocal so lang ist wie dieser Thread (da die starke Referenzkette dieses Werts nicht recycelt wird). unterbrochen werden, bis der Thread die Ausführung abschließt. Wenn der Thread nie endet, kann der angesammelte Wert auch nicht recycelt werden, sodass ein Speicherverlustproblem vorliegt. Die Lösung des Problems besteht darin, ihn zu entfernen( ) Methode zum Löschen der Daten jedes Mal nach der Verwendung von ThreadLocalWas ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?

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;
}

Hier werfen wir einen Blick auf die Stärken und Schwächen des Schlüssels. Der Unterschied zwischen Referenzen

Wenn der Schlüssel als starke Referenz verwendet wird, ist sein Lebenszyklus so lang wie der Thread. Es gibt eine stabile starke Referenzkette und kann nicht recycelt werden, was zu Speicherverlusten führt. Wenn sie als schwache Referenz verwendet wird, kann sie auch in der nachfolgenden Methode „remove()“ besser recycelt werden Entwerfen Sie ThreadLocal im Allgemeinen als privat statisch und verwenden Sie die Methode „remove()“, um sie nach der Verwendung manuell zu löschen

Das obige ist der detaillierte Inhalt vonWas ist das Implementierungsprinzip von ThreadLocal-Thread-Variablen in Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen