So verwenden Sie die Java ThreadLocal-Klasse
Wie im Bild gezeigt:
Als Nächstes zeigen wir Ihnen anhand eines einfachen Beispiels die grundlegende Verwendung von ThreadLocal
package cuit.pymjl.thradlocal; /** * @author Pymjl * @version 1.0 * @date 2022/7/1 10:56 **/ public class MainTest { static ThreadLocal<String> threadLocal = new ThreadLocal<>(); static void print(String str) { //打印当前线程中本地内存中本地变量的值 System.out.println(str + " :" + threadLocal.get()); //清除本地内存中的本地变量 threadLocal.remove(); } public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { //设置线程1中本地变量的值 threadLocal.set("thread1 local variable"); //调用打印方法 print("thread1"); //打印本地变量 System.out.println("after remove : " + threadLocal.get()); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { //设置线程1中本地变量的值 threadLocal.set("thread2 local variable"); //调用打印方法 print("thread2"); //打印本地变量 System.out.println("after remove : " + threadLocal.get()); } }); t1.start(); t2.start(); } }
Das Prinzip von ThreadLocal
ThreadLocal-bezogenes Klassendiagramm # 🎜🎜#
Schauen wir uns zunächst die Klassendiagrammstruktur der ThreadLocal-bezogenen Klasse an, wie in der Abbildung dargestellt:
# 🎜🎜# Wie aus dieser Abbildung ersichtlich ist, gibt es in der Thread-Klasse ein threadLocals und ein inheritableThreadLocals. Beide sind Variablen vom Typ ThreadLocalMap, und ThreadLocalMap ist eine benutzerdefinierte Hashmap. Standardmäßig sind diese beiden Variablen in jedem Thread null und werden nur erstellt, wenn der aktuelle Thread die Set- oder Get-Methode von ThreadLocal zum ersten Mal aufruft. Tatsächlich werden die lokalen Variablen jedes Threads nicht in der ThreadLocal-Instanz gespeichert, sondern in der threadLocals-Variablen des aufrufenden Threads. Mit anderen Worten, lokale Variablen vom Typ ThreadLocal werden in einem bestimmten Thread-Speicherbereich gespeichert. ThreadLocal ist eine Tool-Shell, die den Wert über die Set-Methode in die ThreadLocals des aufrufenden Threads einfügt und speichert. Wenn der aufrufende Thread seine Get-Methode aufruft, entnimmt er ihn zur Verwendung aus der ThreadLocals-Variablen des aktuellen Threads. Wenn der aufrufende Thread nie beendet wird, wird diese lokale Variable immer in der Variablen threadLocals des aufrufenden Threads gespeichert. Wenn die lokale Variable nicht benötigt wird, können Sie die lokale Variable daher aus den threadLocals des aktuellen Threads löschen Remove-Methode der ThreadLocal-Variablen. Warum sind die ThreadLocals in Thread außerdem als Kartenstruktur konzipiert? Offensichtlich, weil jeder Thread mehreren ThreadLocal-Variablen zugeordnet werden kann. Schauen wir uns als Nächstes den Quellcode von ThreadLocals Set, Get und Remove an code>setInitialValues Code
public void set(T value) { // 1.获取当前线程(调用者线程) Thread t = Thread.currentThread(); // 2.以当前线程作为key值,去查找对应的线程变量,找到对应的map ThreadLocalMap map = getMap(t); if (map != null) { // 3.如果map不为null,则直接添加元素 map.set(this, value); } else { // 4.否则就先创建map,再添加元素 createMap(t, value); } }

TerminatingThreadLocal
. Diese Klasse ist neu in JDK11 und existiert nicht in JDK8, daher gibt es in vielen Quellcode-Analysen im Internet keine relevante Beschreibung dieser Klasse. Ich habe mir den Quellcode dieser Klasse angesehen und ihre Funktion sollte darin bestehen, das Problem von ThreadLocal-Speicherlecks zu vermeiden (bei Interesse können Sie den Quellcode überprüfen und mich bei Fehlern bitte korrigieren). Dies ist die offizielle Erklärung: void createMap(Thread t, T firstValue) { /** * 这里是创建一个ThreadLocalMap,以当前调用线程的实例对象为key,初始值为value * 然后放入当前线程的Therad.threadLocals属性里面 */ t.threadLocals = new ThreadLocalMap(this, firstValue); }
remove
ThreadLocalMap getMap(Thread t) { //这里就是直接获取调用线程的成员属性threadlocals return t.threadLocals; }
Summary
In jedem Thread gibt es eine Mitgliedsvariable namens threadLocals, den Typ dieser Variablen ist Hash Map, wobei key die Referenz der von uns definierten ThreadLocal-Variablen ist und value der Wert ist, den wir mit der Set-Methode festgelegt haben. Die lokalen Variablen jedes Threads werden in der Thread-eigenen Speichervariablen threadLocals gespeichert. Wenn der aktuelle Thread nie stirbt, sind diese lokalen Variablen immer vorhanden, sodass es zu einem Speicherüberlauf kommen kann. Denken Sie daher daran, die Methode zum Löschen von ThreadLocal aufzurufen Verwenden Sie lokale Variablen in threadLocals, die dem Thread entsprechen.
ThreadLokaler SpeicherverlustsetInitialValue
的代码
public T get() { // 1.获取当前线程 Thread t = Thread.currentThread(); // 2.获取当前线程的threadlocals,即ThreadLocalMap ThreadLocalMap map = getMap(t); // 3.如果map不为null,则直接返回对应的值 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } // 4.否则,则进行初始化 return setInitialValue(); }
这里我需要补充说明一下TerminatingThreadLocal
angezeigt, und es gibt keine Möglichkeit, auf die Werte dieser Einträge mit Nullschlüsseln zuzugreifen.
Wenn der aktuelle Thread längere Zeit nicht endet, Die Werte dieser Einträge mit Nullschlüsseln werden immer eine starke Referenzkette sein: Thread Ref -> Thread -> Wert kann niemals recycelt werden, was zu Speicherverlusten führt.Tatsächlich wurde diese Situation beim Entwurf von ThreadLocalMap berücksichtigt und einige Schutzmaßnahmen hinzugefügt: Alle Schlüssel im Thread ThreadLocalMap werden beim Abrufen (), Set () und Entfernen () gelöscht. von ThreadLocal sind Nullwerte. Diese passiven vorbeugenden Maßnahmen garantieren jedoch nicht, dass es keine Speicherlecks gibt:
Die Verwendung von static ThreadLocal verlängert den Lebenszyklus von ThreadLocal, was zu Speicherlecks führen kann# 🎜🎜 #
Die Zuweisung mit ThreadLocal und das Nichtaufrufen der Methoden get(), set(), remove() führt zu Speicherlecks#🎜 🎜#Warum schwache Referenzen verwenden?
- Da wir alle wissen, dass die Verwendung schwacher Referenzen zu ThreadLocalMap-Speicherlecks führt, warum verwenden Beamte immer noch schwache Referenzen anstelle starker Referenzen? Dies beginnt mit dem Unterschied zwischen der Verwendung schwacher und starker Referenzen:
Wenn Sie starke Referenzen verwenden: Wir wissen, dass der Lebenszyklus von ThreadLocalMap im Grunde derselbe ist wie der Lebenszyklus von Thread. Wenn der aktuelle Thread nicht beendet wird, wird ThreadLocalMap niemals von GC recycelt und ThreadLocalMap hat einen starken Wert Verweis auf ThreadLocal, dann ThreadLocal Es wird nicht recycelt. Wenn der Thread-Lebenszyklus lang ist und nicht manuell gelöscht wird, führt dies zu einer KV-Akkumulation, was zu OOM führt. Wenn Sie schwache Referenzen verwenden: Objekte in schwachen Referenzen Sie haben einen kurzen Deklarationszeitraum, da im System während der GC das Objekt recycelt wird, solange eine schwache Referenz gefunden wird, unabhängig davon, ob genügend Heap-Speicherplatz vorhanden ist. Wenn die starke Referenz von ThreadLocal recycelt wird, wird auch die schwache Referenz von ThreadLocalMap recycelt. Wenn kv nicht manuell gelöscht wird, führt dies zu einer Wertakkumulation und führt auch zu OOM
-
Im Vergleich dazu Durch die Verwendung schwacher Referenzen kann zumindest garantiert werden, dass OOM nicht durch die Anhäufung von Kartenschlüsseln verursacht wird und der entsprechende Wert beim nächsten Aufruf über die Methoden „remove“, „get“ und „set“ gelöscht werden kann. Es ist ersichtlich, dass die Hauptursache für Speicherverluste nicht in schwachen Referenzen liegt, sondern dass der Lebenszyklus von ThreadLocalMap genauso lang ist wie der von Thread, was zu einer Anhäufung von Werten führt Wenn ein OOM verursacht wird, können wir das richtige Medikament verschreiben und sicherstellen, dass es nach jedem Gebrauch verwendet wird. Rufen Sie einfach die
-Methode von ThreadLocal auf, um es zu bereinigen.
Das obige ist der detaillierte Inhalt vonSo verwenden Sie die Java ThreadLocal-Klasse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Leitfaden zur perfekten Zahl in Java. Hier besprechen wir die Definition, Wie prüft man die perfekte Zahl in Java?, Beispiele mit Code-Implementierung.

Leitfaden zum Zufallszahlengenerator in Java. Hier besprechen wir Funktionen in Java anhand von Beispielen und zwei verschiedene Generatoren anhand ihrer Beispiele.

Leitfaden für Weka in Java. Hier besprechen wir die Einführung, die Verwendung von Weka Java, die Art der Plattform und die Vorteile anhand von Beispielen.

Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

Kapseln sind dreidimensionale geometrische Figuren, die aus einem Zylinder und einer Hemisphäre an beiden Enden bestehen. Das Volumen der Kapsel kann berechnet werden, indem das Volumen des Zylinders und das Volumen der Hemisphäre an beiden Enden hinzugefügt werden. In diesem Tutorial wird erörtert, wie das Volumen einer bestimmten Kapsel in Java mit verschiedenen Methoden berechnet wird. Kapselvolumenformel Die Formel für das Kapselvolumen lautet wie folgt: Kapselvolumen = zylindrisches Volumenvolumen Zwei Hemisphäre Volumen In, R: Der Radius der Hemisphäre. H: Die Höhe des Zylinders (ohne die Hemisphäre). Beispiel 1 eingeben Radius = 5 Einheiten Höhe = 10 Einheiten Ausgabe Volumen = 1570,8 Kubikeinheiten erklären Berechnen Sie das Volumen mithilfe der Formel: Volumen = π × R2 × H (4
