Die ThreadLocal-Klasse kann als ThreadLocalVariable (lokale Thread-Variable) verstanden werden, die Zugriffsschnittstellen oder Methoden wie get und set bereitstellt. Diese Methoden speichern eine unabhängige Kopie für jeden Thread, der die Variable verwendet, sodass get immer den Speicherort der aktuellen Ausführung zurückgibt Thread. Der zuletzt beim Aufruf von set festgelegte Wert. Man kann sich ThreadLocal<T> so vorstellen, dass es ein Map<Thread,T>-Objekt enthält, das für diesen Thread spezifische Werte enthält.
Zusammenfassend lässt sich sagen, dass der Synchronisationsmechanismus für das Problem der gemeinsamen Nutzung von Multithread-Ressourcen die Methode „Zeit gegen Raum austauschen“ verwendet, während ThreadLocal die Methode „Raum gegen Zeit austauschen“ verwendet. Ersteres stellt nur eine Kopie der Variablen für verschiedene Threads bereit, die für den Zugriff in die Warteschlange gestellt werden, während letzteres eine Kopie der Variablen für jeden Thread bereitstellt, sodass gleichzeitig auf sie zugegriffen werden kann, ohne dass sich dies gegenseitig beeinträchtigt.
Schein-ThreadLocal
Kopieren Sie den Codecode wie folgt:
java.util.Collections importieren;
import java.util.HashMap;
java.util.Map importieren;
öffentliche Klasse SimpleThreadLocal<T> {
private Map<Thread, T> valueMap = Collections
.synchronizedMap(new HashMap<Thread, T>());
public void set(T newValue) {
valueMap.put(Thread.currentThread(), newValue); // ①Der Schlüssel ist das Thread-Objekt und der Wert ist eine Kopie der Variablen dieses Threads
}
öffentliches T get() {
Thread currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Gibt die diesem Thread entsprechende Variable zurück
if (o == null && !valueMap.containsKey(currentThread)) { // ③Wenn es nicht in der Map vorhanden ist, fügen Sie es in die Map ein und speichern Sie es.
o = Anfangswert();
valueMap.put(currentThread, o);
}
Rückkehr o;
}
öffentliche Leere entfernen() {
valueMap.remove(Thread.currentThread());
}
protected T initialValue() {
null zurückgeben;
}
}
UtilityThreadLocal
Kopieren Sie den Codecode wie folgt:
Klassenanzahl {
private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
0 zurückgeben;
}
};
öffentliche Ganzzahlerhöhung() {
count.set(count.get() + 1);
return count.get();
}
}
Klasse TestThread implementiert Runnable {
private Anzahl Anzahl;
public TestThread(Count count) {
this.count = count;
}
@Override
public void run() {
// TODO Automatisch generierter Methoden-Stub
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + „/t“ + i
+ "th/t" + count.increase());
}
}
}
öffentliche Klasse TestThreadLocal {
public static void main(String[] args) {
Count count = new Count();
Thread t1 = new Thread(new TestThread(count));
Thread t2 = new Thread(new TestThread(count));
Thread t3 = new Thread(new TestThread(count));
Thread t4 = new Thread(new TestThread(count));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Der ausgegebene Kopiercode lautet wie folgt:
Thread-0 1. 1
Thread-0 2. 2
Thread-0 3. 3
Thread-3 1. 1
Thread-1 1. 1
Thread-1 2. 2
Thread-2 1. 1
Thread-1 3. 3
Thread-3 2. 2
Thread-3 3. 3
Thread-2 2. 2
Thread-2 3. 3