Java Language
ThreadLocal
Suche…
Bemerkungen
Am besten für Objekte SimpleDateFormat
, die beim Aufruf eines Anrufs auf Interna angewiesen sind, ansonsten aber staatenlos sind, wie SimpleDateFormat
, Marshaller
Bei der Verwendung von Random
ThreadLocal sollten Sie ThreadLocalRandom
ThreadLocal Java 8-Funktionsinitialisierung
public static class ThreadLocalExample
{
private static final ThreadLocal<SimpleDateFormat> format =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd_HHmm"));
public String formatDate(Date date)
{
return format.get().format(date);
}
}
Grundlegende ThreadLocal-Verwendung
Java ThreadLocal
wird verwendet, um lokale Thread-Variablen zu erstellen. Es ist bekannt, dass Threads eines Objekts seine Variablen gemeinsam nutzen, sodass die Variable nicht threadsicher ist. Wir können die Synchronisierung für die Thread-Sicherheit verwenden, aber wenn wir die Synchronisation vermeiden möchten, können Sie mit ThreadLocal lokale Variablen für den Thread erstellen, dh, nur dieser Thread kann diese Variablen lesen oder schreiben, sodass die anderen Threads denselben Code ausführen kann nicht auf die ThreadLocal-Variablen zugreifen.
Dies kann verwendet werden, um ThreadLocal
Variablen zu verwenden. in Situationen, in denen Sie einen Thread-Pool haben, wie zum Beispiel in einem Webdienst. Das Erstellen eines SimpleDateFormat
Objekts für jede Anforderung ist beispielsweise sehr zeitaufwändig, und ein statisches Objekt kann nicht erstellt werden, da SimpleDateFormat
nicht SimpleDateFormat
ist. SimpleDateFormat
können wir ein ThreadLocal erstellen, sodass Thread-sichere Vorgänge ausgeführt werden können, ohne dass SimpleDateFormat
muss Zeit.
Der folgende Code zeigt, wie er verwendet werden kann:
Jeder Thread hat seine eigene ThreadLocal
Variable. Mit den Methoden get()
und set()
können sie den Standardwert abrufen oder den lokalen Wert in Thread ändern.
ThreadLocal
Instanzen sind normalerweise private statische Felder in Klassen, die einem Thread den ThreadLocal
möchten.
Hier ein kleines Beispiel, das die Verwendung von ThreadLocal im Java-Programm zeigt und beweist, dass jeder Thread eine eigene Kopie der ThreadLocal
Variablen hat.
package com.examples.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
public class ThreadLocalExample implements Runnable{
// SimpleDateFormat is not thread-safe, so give one to each thread
// 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 static void main(String[] args) throws InterruptedException {
ThreadLocalExample obj = new ThreadLocalExample();
for(int i=0 ; i<10; i++){
Thread t = new Thread(obj, ""+i);
Thread.sleep(new Random().nextInt(1000));
t.start();
}
}
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
formatter.set(new SimpleDateFormat());
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
}
}
Ausgabe:
Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a
Wie aus der Ausgabe hervorgeht, hat Thread-0 den Wert des Formatierers geändert, der Standardformatierer von Thread-2 ist jedoch mit dem initialisierten Wert identisch.
Mehrere Threads mit einem gemeinsamen Objekt
In diesem Beispiel haben wir nur ein Objekt, das jedoch von verschiedenen Threads gemeinsam genutzt wird. Eine normale Verwendung von Feldern zum Speichern des Zustands wäre nicht möglich, da der andere Thread dies auch sehen würde (oder wahrscheinlich nicht sehen würde).
public class Test {
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(foo, "Thread 1").start();
new Thread(foo, "Thread 2").start();
}
}
In Foo zählen wir von Null an. Anstatt den Status in einem Feld zu speichern, speichern wir unsere aktuelle Nummer im ThreadLocal-Objekt, das statisch zugänglich ist. Beachten Sie, dass die Synchronisierung in diesem Beispiel nicht mit der Verwendung von ThreadLocal zusammenhängt, sondern eine bessere Konsolenausgabe gewährleistet.
public class Foo implements Runnable {
private static final int ITERATIONS = 10;
private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
synchronized (threadLocal) {
//Although accessing a static field, we get our own (previously saved) value.
int value = threadLocal.get();
System.out.println(Thread.currentThread().getName() + ": " + value);
//Update our own variable
threadLocal.set(value + 1);
try {
threadLocal.notifyAll();
if (i < ITERATIONS - 1) {
threadLocal.wait();
}
} catch (InterruptedException ex) {
}
}
}
}
}
In der Ausgabe sehen wir, dass jeder Thread für sich selbst zählt und nicht den Wert des anderen verwendet:
Thread 1: 0
Thread 2: 0
Thread 1: 1
Thread 2: 1
Thread 1: 2
Thread 2: 2
Thread 1: 3
Thread 2: 3
Thread 1: 4
Thread 2: 4
Thread 1: 5
Thread 2: 5
Thread 1: 6
Thread 2: 6
Thread 1: 7
Thread 2: 7
Thread 1: 8
Thread 2: 8
Thread 1: 9
Thread 2: 9