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:
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()-Methode
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 werdenThreadLocal-SpeicherverlustproblemIn 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 ThreadLocal
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 ReferenzenWenn 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!