Класс ThreadLocal можно понимать как ThreadLocalVariable (локальная переменная потока), которая предоставляет интерфейсы доступа или методы, такие как get и set. Эти методы хранят независимую копию для каждого потока, использующего переменную, поэтому get всегда возвращает местоположение текущего выполнения. поток Последнее значение, установленное при вызове set. ThreadLocal<T> можно рассматривать как содержащий объект Map<Thread,T>, содержащий значения, специфичные для этого потока.
Подводя итог, можно сказать, что для проблемы многопоточного совместного использования ресурсов механизм синхронизации использует метод «обмена времени на пространство», а ThreadLocal использует метод «обмена пространства на время». Первый предоставляет только копию переменной для разных потоков, стоящих в очереди на доступ, а второй предоставляет копию переменной для каждого потока, поэтому к ней можно обращаться одновременно, не влияя друг на друга.
Mock ThreadLocal
Скопируйте код кода следующим образом:
импортировать java.util.Collections;
импортировать java.util.HashMap;
импортировать java.util.Map;
общественный класс SimpleThreadLocal<T> {
частная карта<Thread, T> valueMap = Коллекции
.synchronizedMap(new HashMap<Thread, T>());
public void set(T newValue) {
valueMap.put(Thread.currentThread(), newValue); // ①Ключ — это объект потока, а значение — копия переменной этого потока;
}
общественный T get () {
Поток currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Возвращаем переменную, соответствующую этому потоку;
if (o == null && !valueMap.containsKey(currentThread)) { // ③Если его нет на карте, поместите его на карту и сохраните.
о = начальное значение();
valueMap.put(currentThread, о);
}
вернуться о;
}
общественная недействительность удалить () {
valueMap.remove(Thread.currentThread());
}
защищенный T начальное значение() {
вернуть ноль;
}
}
УтилитаThreadLocal
Скопируйте код кода следующим образом:
количество классов {
частный SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@Override
защищенное целое число InitialValue() {
вернуть 0;
}
};
публичное целочисленное увеличение() {
count.set(count.get() + 1);
вернуть счетчик.get();
}
}
класс TestThread реализует Runnable {
частный подсчет подсчета;
public TestThread (счетчик) {
this.count = количество;
}
@Override
общественный недействительный запуск () {
// TODO Автоматически сгенерированная заглушка метода
for (int я = 1; я <= 3; я++) {
System.out.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + count.increase());
}
}
}
общественный класс TestThreadLocal {
public static void main(String[] args) {
Количество счетчиков = новый счетчик();
Поток t1 = новый поток (новый TestThread (количество));
Поток t2 = новый поток (новый TestThread (количество));
Поток t3 = новый поток (новый TestThread (количество));
Поток t4 = новый поток (новый TestThread (количество));
t1.start();
т2.старт();
т3.старт();
т4.старт();
}
}
Выходной код копирования выглядит следующим образом:
Тема-0 1-й 1
Тема-0 2-я 2
Тема-0 3-я 3
Тема-3 1-я 1
Тема-1 1-я 1
Тема-1 2-я 2
Тема-2 1-я 1
Тема-1 3-я 3
Тема-3 2-я 2
Тема-3 3-я 3
Тема-2 2-я 2
Тема-2 3-я 3