it-swarm.com.de

Wann und wie sollte ich eine ThreadLocal-Variable verwenden?

Wann sollte ich eine Variable ThreadLocal verwenden?

Wie wird es benutzt?

810
Sasha

Eine mögliche (und übliche) Verwendung ist, wenn Sie ein Objekt haben, das nicht threadsicher ist, Sie jedoch den Zugriff von synchronize auf dieses Objekt vermeiden möchten (ich sehe Sie an, SimpleDateFormat ). Geben Sie stattdessen jedem Thread eine eigene Instanz des Objekts.

Zum Beispiel:

public class Foo
{
    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };

    public String formatIt(Date date)
    {
        return formatter.get().format(date);
    }
}

Dokumentation .

803
overthink

Da eine ThreadLocal eine Referenz auf Daten innerhalb einer bestimmten Thread ist, können Sie mit Classloading-Lecks enden, wenn Sie ThreadLocals in Anwendungsservern verwenden, die Thread-Pools verwenden. Sie müssen sehr vorsichtig sein, wenn Sie ThreadLocals bereinigen, die Sie get() oder set() verwenden, indem Sie die remove()-Methode von ThreadLocal verwenden.

Wenn Sie nicht bereinigen, wenn Sie fertig sind, verbleiben alle Verweise auf Klassen, die als Teil einer bereitgestellten Webapp geladen werden, im permanenten Heap und werden niemals Müll gesammelt. Durch das erneute Bereitstellen/Aufheben der Bereitstellung der Webapp wird der Verweis auf jede Thread auf die Klasse (n) Ihrer Webapp nicht bereinigt, da die Thread nicht zu Ihrer Webapp gehört. Bei jeder nachfolgenden Bereitstellung wird eine neue Instanz der Klasse erstellt, die niemals als Garbage-Collection erfasst wird.

Am Ende kommt es aufgrund von Java.lang.OutOfMemoryError: PermGen space zu Speicherausfällen, und nach einigem Googeln wird -XX:MaxPermSize wahrscheinlich nur erhöht, anstatt den Fehler zu beheben.

Wenn diese Probleme auftreten, können Sie feststellen, welcher Thread und welche Klasse diese Verweise beibehält, indem Sie Eclipse's Memory Analyzer und/oder durch Befolgen der Frank Kieviets Anleitung und followup verwenden.

Update: Wiederentdeckter Blogeintrag von Alex Vasseur der mir geholfen hat, einige ThreadLocal-Probleme aufzuspüren, die ich hatte.

395
Phil M

Viele Frameworks verwenden ThreadLocals, um einen Kontext zu verwalten, der sich auf den aktuellen Thread bezieht. Wenn beispielsweise die aktuelle Transaktion in einem ThreadLocal gespeichert ist, müssen Sie sie nicht bei jedem Methodenaufruf als Parameter übergeben, falls jemand im Stapel Zugriff darauf benötigt. Webanwendungen speichern möglicherweise Informationen zu der aktuellen Anforderung und Sitzung in einem ThreadLocal, sodass die Anwendung einfach auf sie zugreifen kann. Mit Guice können Sie ThreadLocals verwenden, wenn Sie benutzerdefinierte Bereiche für die injizierten Objekte implementieren (Guices Standard Servlet-Bereiche verwenden sie höchstwahrscheinlich auch).

ThreadLocals sind eine Art globaler Variablen (obwohl sie etwas weniger böse sind, weil sie auf einen Thread beschränkt sind). Sie sollten daher vorsichtig sein, wenn Sie sie verwenden, um unerwünschte Nebenwirkungen und Speicherlecks zu vermeiden. Entwerfen Sie Ihre APIs so, dass die ThreadLocal-Werte immer automatisch gelöscht werden, wenn sie nicht mehr benötigt werden, und dass eine falsche Verwendung der API nicht möglich ist (zum Beispiel so ). ThreadLocals können verwendet werden, um den Code sauberer zu machen, und in einigen seltenen Fällen sind sie die einzige Möglichkeit, etwas zum Laufen zu bringen (in meinem aktuellen Projekt gab es zwei solcher Fälle; sie sind dokumentiert hier unter "Statische Felder und Global" Variablen").

142
Esko Luontola

Wenn Sie in Java über ein Datum verfügen, das je nach Thread variieren kann, können Sie das Datum an jede Methode weitergeben, die es benötigt (oder möglicherweise benötigt), oder das Datum mit dem Thread verknüpfen. Das Übergeben des Datums an alle Stellen kann praktikabel sein, wenn alle Ihre Methoden bereits eine gemeinsame "Kontext" -Variable übergeben müssen. 

Ist dies nicht der Fall, möchten Sie Ihre Methodensignaturen möglicherweise nicht mit einem zusätzlichen Parameter überladen. In einer Welt ohne Threading könnten Sie das Problem mit dem Java-Äquivalent einer globalen Variablen lösen. In einem Thread-Word ist das Äquivalent einer globalen Variablen eine lokale Thread-Variable.

44
user100464

Es gibt ein sehr gutes Beispiel in Buch Java Concurrency in Practice. Wo der Autor ( Joshua Bloch ) erläutert, ist die Thread-Beschränkung eine der einfachsten Methoden, um Threadsicherheit zu erreichen, und ThreadLocal ist ein formelleres Mittel zur Aufrechterhaltung der Thread-Beschränkung. Am Ende erklärt er auch, wie Menschen ihn als globale Variablen missbrauchen können.

Ich habe den Text aus dem erwähnten Buch kopiert, aber der Code 3.10 fehlt, da es nicht wichtig ist, zu verstehen, wo ThreadLocal verwendet werden sollte.

Thread-lokale Variablen werden häufig verwendet, um das Teilen in Designs zu verhindern, die auf veränderlichen Singletons oder globalen Variablen basieren. Beispielsweise kann eine Anwendung mit einem einzigen Thread eine globale Datenbankverbindung aufrechterhalten, die beim Start initialisiert wird, um zu vermeiden, dass an jede Methode eine Verbindung übergeben werden muss. Da JDBC-Verbindungen möglicherweise nicht threadsicher sind, ist eine Multithread-Anwendung, die eine globale Verbindung ohne zusätzliche Koordination verwendet, auch nicht threadsicher. Durch Verwenden einer ThreadLocal zum Speichern der JDBC-Verbindung, wie in ConnectionHolder in Listing 3.10, hat jeder Thread eine eigene Verbindung.

ThreadLocal wird häufig bei der Implementierung von Anwendungsframeworks verwendet. Beispielsweise verknüpfen J2EE-Container einen Transaktionskontext mit einem ausgeführten Thread für die Dauer eines EJB-Aufrufs. Dies kann leicht mit einem statischen Thread-Local implementiert werden, das den Transaktionskontext enthält: Wenn der Framework-Code bestimmen muss, welche Transaktion gerade ausgeführt wird, ruft er den Transaktionskontext aus dieser ThreadLocal ab. Dies ist insofern praktisch, als es die Notwendigkeit reduziert, Ausführungskontextinformationen an jede Methode zu übergeben, aber den Code, der diesen Mechanismus verwendet, an das Framework koppelt.

ThreadLocal kann leicht missbraucht werden, indem die Thread-Confinement-Eigenschaft als Lizenz für die Verwendung globaler Variablen oder als Mittel zum Erstellen „versteckter“ Methodenargumente behandelt wird. Wie globale Variablen können Thread-lokale Variablen die Wiederverwendbarkeit beeinträchtigen und versteckte Kopplungen zwischen Klassen einführen. Sie sollten daher mit Vorsicht verwendet werden.

14
Rakesh Chauhan

Im Wesentlichen, wenn Sie den Wert einer Variablen benötigen, um auf den aktuellen Thread angewiesen zu sein, und es für Sie nicht geeignet ist, den Wert auf andere Weise an den Thread anzuhängen (beispielsweise Subclassing-Thread).

Ein typischer Fall ist, dass ein anderes Framework den Thread erstellt hat, in dem Ihr Code ausgeführt wird, z. ein Servlet-Container, oder wo es sinnvoller ist, ThreadLocal zu verwenden, da Ihre Variable dann "an ihrem logischen Ort" ist (und nicht eine Variable, die an einer Thread-Unterklasse oder in einer anderen Hash-Map hängt).

Auf meiner Website habe ich einige weitere Diskussion und Beispiele für die Verwendung von ThreadLocal , die ebenfalls von Interesse sein könnten.

Einige Leute befürworten die Verwendung von ThreadLocal, um in bestimmten gleichzeitigen Algorithmen, in denen Sie eine Thread-Nummer benötigen, eine "Thread-ID" an jeden Thread anzuhängen (siehe z. B. Herlihy & Shavit). Überprüfen Sie in solchen Fällen, ob Sie wirklich einen Vorteil haben!

13
Neil Coffey

Der Webapp-Server behält möglicherweise einen Thread-Pool bei, und eine ThreadLocal-Variable sollte vor der Antwort an den Client entfernt werden. Der aktuelle Thread kann daher bei der nächsten Anforderung erneut verwendet werden.

9
znlyj

Die Dokumentation sagt es sehr gut: "Jeder Thread, der auf [eine lokale Variable des Threads] (über seine get- oder set-Methode) zugreift, hat eine eigene, unabhängig initialisierte Kopie der Variablen".

Sie verwenden eins, wenn jeder Thread eine eigene Kopie von etwas haben muss. Standardmäßig werden Daten von Threads gemeinsam genutzt.

9
RichieHindle
  1. ThreadLocal in Java wurde in JDK 1.2 eingeführt, wurde jedoch später in JDK 1.5 erstellt, um die Typsicherheit für die ThreadLocal-Variable einzuführen.

  2. ThreadLocal kann mit dem Thread-Bereich verknüpft werden. Der gesamte Code, der von Thread ausgeführt wird, hat Zugriff auf ThreadLocal-Variablen, aber zwei Threads können sich nicht gegenseitig die ThreadLocal-Variable sehen.

  3. Jeder Thread enthält eine exklusive Kopie der ThreadLocal-Variablen, die für die Garbage-Collection in Frage kommt, nachdem der Thread normalerweise beendet wurde oder abgelaufen ist (normalerweise oder aufgrund einer Ausnahme).

  4. ThreadLocal-Variablen in Java sind im Allgemeinen private statische Felder in Klassen und behalten ihren Status in Thread bei.

Lesen Sie mehr: http://javarevisited.blogspot.com/2012/05/how-to-use-threadlocal-in-Java-benefits.html#ixzz2XltgbHTK

8
Abhijit Gaikwad

Zwei Anwendungsfälle, in denen eine Threadlocal-Variable verwendet werden kann - 
1- Wenn wir die Anforderung haben, einem Thread einen Status zuzuordnen (z. B. eine Benutzer-ID oder eine Transaktions-ID). Dies geschieht normalerweise bei einer Webanwendung, bei der jeder Anforderung, die an ein Servlet gesendet wird, eine eindeutige Transaktions-ID zugeordnet ist.

// This class will provide a thread local variable which
// will provide a unique ID for each thread
class ThreadId {
    // Atomic integer containing the next thread ID to be assigned
    private static final AtomicInteger nextId = new AtomicInteger(0);

    // Thread local variable containing each thread's ID
    private static final ThreadLocal<Integer> threadId =
        ThreadLocal.<Integer>withInitial(()-> {return nextId.getAndIncrement();});

    // Returns the current thread's unique ID, assigning it if necessary
    public static int get() {
        return threadId.get();
    }
}

Beachten Sie, dass hier die Methode withInitial mit einem Lambda-Ausdruck implementiert wird.
2- Ein anderer Anwendungsfall liegt vor, wenn wir eine Thread-sichere Instanz haben möchten und keine Synchronisierung verwenden möchten, da die Performancekosten bei der Synchronisierung mehr sind. Ein solcher Fall liegt vor, wenn SimpleDateFormat verwendet wird. Da SimpleDateFormat nicht threadsicher ist, müssen wir einen Mechanismus bereitstellen, um es threadsicher zu machen. 

public class ThreadLocalDemo1 implements Runnable {
    // threadlocal variable is created
    private static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue(){
            System.out.println("Initializing SimpleDateFormat for - " + Thread.currentThread().getName() );
            return new SimpleDateFormat("dd/MM/yyyy");
        }
    };

    public static void main(String[] args) {
        ThreadLocalDemo1 td = new ThreadLocalDemo1();
        // Two threads are created
        Thread t1 = new Thread(td, "Thread-1");
        Thread t2 = new Thread(td, "Thread-2");
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        System.out.println("Thread run execution started for " + Thread.currentThread().getName());
        System.out.println("Date formatter pattern is  " + dateFormat.get().toPattern());
        System.out.println("Formatted date is " + dateFormat.get().format(new Date()));
    } 

}
7
infoj

Sie müssen mit dem ThreadLocal-Muster sehr vorsichtig sein. Es gibt einige wichtige Nachteile wie Phil, aber eine, die nicht erwähnt wurde, ist sicherzustellen, dass der Code, der den ThreadLocal-Kontext einrichtet, nicht "wiedereintritt".

Wenn der Code, der die Informationen festlegt, ein zweites oder drittes Mal ausgeführt wird, können schlechte Dinge passieren, da die Informationen in Ihrem Thread möglicherweise mutieren, wenn Sie nicht erwartet haben. Stellen Sie daher sicher, dass die ThreadLocal-Informationen nicht festgelegt wurden, bevor Sie sie erneut festlegen.

4
Jeff Richley

Seit der Veröffentlichung von Java 8 gibt es eine deklarativere Möglichkeit, ThreadLocal zu initialisieren:

ThreadLocal<Cipher> local = ThreadLocal.withInitial(() -> "init value");

Bis zur Veröffentlichung von Java 8 mussten Sie Folgendes tun:

ThreadLocal<String> local = new ThreadLocal<String>(){
    @Override
    protected String initialValue() {
        return "init value";
    }
};

Wenn die Instantiierungsmethode (Konstruktor, Factory-Methode) der Klasse, die für ThreadLocal verwendet wird, keine Parameter enthält, können Sie außerdem einfach Methodenreferenzen (in Java 8 eingeführt) verwenden:

class NotThreadSafe {
    // no parameters
    public NotThreadSafe(){}
}

ThreadLocal<NotThreadSafe> container = ThreadLocal.withInitial(NotThreadSafe::new);

Hinweis: Die Auswertung ist träge, da Sie Java.util.function.Supplier-Lambda übergeben, das nur ausgewertet wird, wenn ThreadLocal#get aufgerufen wird, der Wert jedoch zuvor nicht ausgewertet wurde.

4
Andrii Abramov

wann?

Wenn ein Objekt nicht threadsicher ist, anstatt der Synchronisierung, die die Skalierbarkeit behindert, ein Objekt für jeden Thread bereitzustellen, und den Thread-Gültigkeitsbereich beibehalten (ThreadLocal). Eines der am häufigsten verwendeten, aber nicht Thread-sicheren Objekte sind Datenbankverbindung und JMSConnection. 

Wie ?

Ein Beispiel ist das Spring Framework, das ThreadLocal stark für die Verwaltung von Transaktionen im Hintergrund verwendet, indem diese Verbindungsobjekte in ThreadLocal-Variablen gehalten werden. Wenn auf hoher Ebene eine Transaktion gestartet wird, erhält sie die Verbindung (und deaktiviert das automatische Festschreiben) und behält sie in ThreadLocal. Bei weiteren DB-Aufrufen verwendet es dieselbe Verbindung, um mit DB zu kommunizieren. Am Ende nimmt es die Verbindung von ThreadLocal, schreibt die Transaktion fest (oder Rollback) und gibt die Verbindung frei. 

Ich denke, log4j verwendet ThreadLocal zur Pflege von MDC.

4
Limestone

Wie von @unknown (google) erwähnt, wird eine globale Variable definiert, in der der Wert, auf den verwiesen wird, in jedem Thread eindeutig sein kann. Normalerweise werden dazu Kontextinformationen gespeichert, die mit dem aktuellen Ausführungsthread verknüpft sind. 

Wir verwenden es in einer Java EE-Umgebung, um die Benutzeridentität an Klassen zu übergeben, die nicht Java EE-fähig sind (keinen Zugriff auf HttpSession oder den EJB SessionContext). Auf diese Weise kann der Code, der die Identität für sicherheitsbasierte Vorgänge verwendet, von überall auf die Identität zugreifen, ohne dass er bei jedem Methodenaufruf explizit übergeben werden muss.

Der Anforderungs-/Antwortzyklus der Operationen in den meisten Java EE-Aufrufen macht diese Art der Verwendung einfach, da durch sie klar definierte Ein- und Ausstiegspunkte festgelegt und die ThreadLocal-Einstellung aufgehoben wird.

3
Robin

ThreadLocal ist nützlich, wenn Sie einen Status haben möchten, der nicht von verschiedenen Threads gemeinsam genutzt werden soll, aber von jedem Thread aus während seiner gesamten Lebensdauer zugänglich sein sollte.

Stellen Sie sich als Beispiel eine Webanwendung vor, bei der jede Anforderung von einem anderen Thread bedient wird. Stellen Sie sich vor, Sie benötigen für jede Anforderung ein einziges Mal Daten, was in der Berechnung recht teuer ist. Diese Daten haben sich jedoch möglicherweise für jede eingehende Anforderung geändert, was bedeutet, dass Sie keinen einfachen Cache verwenden können. Eine einfache, schnelle Lösung für dieses Problem wäre, eine Variable ThreadLocal zu haben, die Zugriff auf diese Daten hat, so dass Sie sie nur einmal für jede Anforderung berechnen müssen. Natürlich kann dieses Problem auch ohne die Verwendung von ThreadLocal gelöst werden, ich habe es jedoch zu Illustrationszwecken entwickelt. 

Denken Sie jedoch daran, dass ThreadLocals im Wesentlichen eine Form eines globalen Staates sind. Folglich hat es viele andere Implikationen und sollte nur verwendet werden, wenn alle anderen möglichen Lösungen in Betracht gezogen werden. 

3
Dimos

Nichts wirklich Neues hier, aber ich habe heute entdeckt, dass ThreadLocal sehr nützlich ist, wenn Bean Validation in einer Webanwendung verwendet wird. Überprüfungsnachrichten sind lokalisiert, verwenden jedoch standardmäßig Locale.getDefault(). Sie können Validator mit einer anderen MessageInterpolator konfigurieren. Sie können die Locale jedoch nicht angeben, wenn Sie validate aufrufen. Sie könnten also einen statischen ThreadLocal<Locale> (oder besser noch einen allgemeinen Container mit anderen Dingen, die Sie möglicherweise ThreadLocal verwenden müssen, erstellen und dann Ihre benutzerdefinierte MessageInterpolator die Locale auswählen. Als nächstes schreiben Sie eine ServletFilter, die einen Sitzungswert oder request.getLocale() verwendet Wählen Sie das Gebietsschema aus und speichern Sie es in Ihrer ThreadLocal-Referenz.

3
Colselaw

ThreadLocal gewährleistet den Zugriff auf das veränderliche Objekt durch mehrere Threads in der nicht synchronisierten Methode werden synchronisiert, dh das veränderliche Objekt soll innerhalb der Methode unveränderlich sein. 

Diese wird erreicht, indem für jeden Thread eine neue Instanz eines veränderlichen Objekts angegeben wird versuchen Sie es aufzurufen. Es ist also eine lokale Kopie des jeweiligen Threads. Dies ist etwas Hacken Sie die Instanzvariable in einer Methode, auf die wie eine .__ zugegriffen werden kann. lokale Variable. Wie Sie wissen, ist die lokale Variable nur verfügbar zu dem Thread ist ein Unterschied; lokale Variablen der Methode werden nicht steht dem Thread zur Verfügung, sobald die Ausführung der Methode abgeschlossen ist, und zwar als veränderlich Mit threadlocal gemeinsam genutztes Objekt ist in mehreren .__ verfügbar. Methoden, bis wir es aufräumen.

Per Definition:

Mit der ThreadLocal-Klasse in Java können Sie Variablen erstellen, die Nur von demselben Thread gelesen und geschrieben werden. Also auch wenn zwei Threads führen den gleichen Code aus und der Code hat einen Verweis auf eine ThreadLocal-Variable, dann können die beiden Threads einander nicht sehen ThreadLocal-Variablen.

Jede Thread in Java enthält ThreadLocalMap
Woher 

Key = One ThreadLocal object shared across threads.
value = Mutable object which has to be used synchronously, this will be instantiated for each thread.

Das ThreadLocal erreichen: 

Erstellen Sie nun eine Wrapper-Klasse für ThreadLocal, die das veränderliche Objekt wie unten (mit oder ohne initialValue()) aufnehmen wird. 
Getter und Setter dieses Wrappers funktionieren jetzt mit der Threadlocal-Instanz anstelle eines veränderlichen Objekts.

Wenn getter () von threadlocal in der Threadlocalmap der Thread keinen Wert gefunden hat; dann ruft es initialValue () auf, um seine private Kopie in Bezug auf den Thread zu erhalten.

class SimpleDateFormatInstancePerThread {

    private static final ThreadLocal<SimpleDateFormat> dateFormatHolder = new ThreadLocal<SimpleDateFormat>() {

        @Override
        protected SimpleDateFormat initialValue() {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd") {
                UUID id = UUID.randomUUID();
                @Override
                public String toString() {
                    return id.toString();
                };
            };
            System.out.println("Creating SimpleDateFormat instance " + dateFormat +" for Thread : " + Thread.currentThread().getName());
            return dateFormat;
        }
    };

    /*
     * Every time there is a call for DateFormat, ThreadLocal will return calling
     * Thread's copy of SimpleDateFormat
     */
    public static DateFormat getDateFormatter() {
        return dateFormatHolder.get();
    }

    public static void cleanup() {
        dateFormatHolder.remove();
    }
}

Jetzt ruft wrapper.getDateFormatter()threadlocal.get() auf und prüft, ob currentThread.threadLocalMapthis (threadlocal) enthält.
Wenn ja, wird der Wert (SimpleDateFormat) für die entsprechende Threadlocal-Instanz zurückgegeben 
else fügt die Map mit dieser fadenlokalen Instanz initialValue () hinzu. 

Hiermit wird Fadensicherheit für diese veränderliche Klasse erreicht. Jeder Thread arbeitet mit seiner eigenen veränderlichen Instanz, jedoch mit derselben ThreadLocal-Instanz. Mittel Alle Threads verwenden dieselbe ThreadLocal-Instanz als Schlüssel, jedoch eine andere SimpleDateFormat-Instanz als Wert.

https://github.com/skanagavelu/yt.tech/blob/master/src/ThreadLocalTest.Java

3

Thread-lokale Variablen werden häufig verwendet, um das Teilen in Designs zu verhindern, die auf Veränderlichen Singletons oder globalen Variablen basieren. 

Sie können in Szenarien wie dem Herstellen einer separaten JDBC-Verbindung für jeden Thread verwendet werden, wenn Sie keinen Verbindungspool verwenden.

private static ThreadLocal<Connection> connectionHolder
           = new ThreadLocal<Connection>() {
      public Connection initialValue() {
           return DriverManager.getConnection(DB_URL);
          }
     };

public static Connection getConnection() {
      return connectionHolder.get();
} 

Wenn Sie getConnection aufrufen, wird eine Verbindung zurückgegeben, die diesem Thread zugeordnet ist. Das gleiche kann mit anderen Eigenschaften wie dateformat und Transaktionskontext geschehen, den Sie nicht zwischen Threads teilen möchten. 

Sie hätten auch lokale Variablen für dasselbe verwenden können, aber diese Ressource benötigt normalerweise Zeit bei der Erstellung, sodass Sie sie nicht immer wieder erstellen möchten, wenn Sie Geschäftslogik damit ausführen. ThreadLocal-Werte werden jedoch im Thread-Objekt selbst gespeichert. Sobald der Thread Müll gesammelt wurde, sind auch diese Werte nicht mehr verfügbar.

Dieser link erklärt die Verwendung von ThreadLocal sehr gut.

2
bpjoshi

[Zur Referenz] ThreadLocal kann Aktualisierungsprobleme eines gemeinsam genutzten Objekts nicht lösen. Es wird empfohlen, ein staticThreadLocal-Objekt zu verwenden, das von allen Operationen im selben Thread gemeinsam genutzt wird. __ [mandatory] remove () - Methode muss von ThreadLocal-Variablen implementiert werden, insbesondere wenn Threadpools verwendet werden, in denen Threads häufig wiederverwendet werden. Andernfalls kann sich dies auf die nachfolgende Geschäftslogik auswirken und unerwartete Probleme wie Speicherverlust verursachen.

1
Young

ThreadLocal ist eine speziell von JVM bereitgestellte Funktion, die nur einen isolierten Speicherplatz für Threads bereitstellt. Wie der Wert der Instanzbereichsvariablen sind sie nur an eine gegebene Instanz einer Klasse gebunden. Jedes Objekt hat seine einzigen Werte und kann keinen anderen Wert sehen. Das ist das Konzept der ThreadLocal-Variablen. Sie sind lokal für den Thread im Sinne von Objektinstanzen, die kein anderer Thread ist, außer der, der ihn erstellt hat, und kann ihn nicht sehen. Siehe hier

import Java.util.concurrent.atomic.AtomicInteger;
import Java.util.stream.IntStream;


public class ThreadId {
private static final AtomicInteger nextId = new AtomicInteger(1000);

// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> nextId.getAndIncrement());


// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
    return threadId.get();
}

public static void main(String[] args) {

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

    new Thread(() -> IntStream.range(1, 3).forEach(i -> {
        System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
    })).start();

}
}
0
Ajay

Zwischenspeichern, manchmal müssen Sie den gleichen Wert viel Zeit berechnen, sodass Sie den letzten Satz von Eingaben in einer Methode speichern und das Ergebnis beschleunigen können. Durch die Verwendung von Thread Local Storage müssen Sie nicht über das Sperren nachdenken.

0
Ian Ringrose

Es gibt 3 Szenarien für die Verwendung eines class helper wie SimpleDateFormat in Multithread-Code. Am besten verwenden Sie ThreadLocal

Szenarien

1 - Verwenden von like share object mithilfe von lock or synchronisation Mechanismus, der die App langsam macht

2 - Verwendung als lokales Objekt innerhalb einer Methode

In diesem Szenario haben wir 4 Thread jede ruft eine Methode 1000 auf Zeit
4000 SimpleDateFormat Objekt erstellt und darauf warten, dass GC sie löscht

3 - Verwenden von ThreadLocal

wenn wir 4 Threads haben und jedem Thread eine SimpleDateFormat-Instanz gegeben haben
also haben wir 4 Threads, 4 Objekte von SimpleDateFormat.

Es ist kein Sperrmechanismus und keine Objekterstellung und -zerstörung erforderlich. (Gute zeitliche und räumliche Komplexität)

0
mohsen.nour

Threadlocal bietet eine sehr einfache Möglichkeit, die Wiederverwendbarkeit von Objekten ohne Kosten zu erreichen.

Ich hatte eine Situation, in der mehrere Threads bei jeder Aktualisierungsbenachrichtigung ein Image mit veränderbarem Cache erstellten.

Ich habe für jeden Thread ein Threadlocal verwendet, und dann musste jeder Thread nur das alte Image zurücksetzen und es bei jeder Aktualisierungsbenachrichtigung erneut aus dem Cache aktualisieren.

Übliche wiederverwendbare Objekte aus Objektpools sind mit Thread-Sicherheitskosten verbunden, während dieser Ansatz keine hat. 

0
Dev Amitabh

Mit der Klasse ThreadLocal in Java können Sie Variablen erstellen, die nur von demselben Thread gelesen und geschrieben werden können. Selbst wenn zwei Threads denselben Code ausführen und der Code eine Referenz auf eine ThreadLocal-Variable hat, können die beiden Threads die ThreadLocal-Variablen des jeweils anderen nicht sehen.

Weiterlesen

0
Pritesh Patel