Топ-100ThreadLocal в Java: переменные потока - CodOrbits
LogoCodOrbits

Раздел: Многопоточность

В этом разделе вы узнаете, как использовать многопоточность в Java для повышения производительности и параллельной обработки.

Все разделы
Иконка Многопоточность

ThreadLocal в Java: переменные потока

Last updated: 7 мая 2025 г.

ThreadLocalпеременная ПОТОКА. Это не переменная объекта потока, а именно переменная ПОТОКА. То есть она принадлежит только одному потоку и существует только в одном потоке.

В примере ниже мы создаем объект потока threadDemo, который передаем на выполнение в три потока. То есть три потока будут работать с одним и тем же объектом.

Если переменная НЕ ThreadLocal и эта переменная в этом объекте меняется каким-то одним потоком, то эта переменная будет измененной и в других потоках, так как они работают с одним и тем же объектом.

Но ThreadLocal переменная не такая. Если ThreadLocal переменную в объекте изменит какой-то один поток, то она не будет измененной в других потоках не смотря на то, что они работают с одним объектом. Она будет измененной только в потоке, который ее изменил.

Пример программы:

1class SomeThread implements Runnable {
2    // локальная переменная объекта класса
3    int counter;
4    
5    // локальная переменная потока
6    ThreadLocal<Integer> threadLocalCounter = new ThreadLocal<>();
7    
8    // то есть, как видим, есть переменные ОБЪЕКТА,
9    // а есть переменные ПОТОКА.
10    // Смотри более подробно после кода
11    
12    public void run() {
13        counter++;
14
15        if (threadLocalCounter.get() != null) {
16            // запись в переменную ThreadLocal
17            // через метод set
18            threadLocalCounter.set(threadLocalCounter.get() + 1);
19        } else {
20            threadLocalCounter.set(0);
21        }
22
23        System.out.println("Counter: " + counter);
24        System.out.println("threadLocalCounter: " + threadLocalCounter.get());
25    }
26}
27
28class ThreadLocalExample {
29    public static void main(String[] args) {
30        SomeThread threadDemo = new SomeThread();
31
32        Thread t1 = new Thread(threadDemo);
33        Thread t2 = new Thread(threadDemo);
34        Thread t3 = new Thread(threadDemo);
35
36        t1.start();
37        try {
38            Thread.sleep(200);
39        } catch (InterruptedException e) {}
40
41        t2.start();
42        try {
43            Thread.sleep(200);
44        } catch (InterruptedException e) {}
45
46        t3.start();
47    }
48}

Вывод:

Как можно увидеть в консоли, переменную counter меняли все три потока, а переменная threadLocalCounter была у каждого потока своя личная и в каждом из потоков она только успела стать 0.

Как можно увидеть ThreadLocal иногда не заменим, например в этом случае, когда создать локальную переменную для потока можно только с помощью ThreadLocal, потому что объект один, это threadDemo и все потоки работают с ним, и соответственно, например, локальная переменная counter для всех потоков общая и все потоки изменяют ее в этом объекте, а чтобы создать личную для каждого потока работающего с объектом threadDemo необходимо использовать ThreadLocal.

Search Icon

То есть counter – переменная объекта, threadLocalCounter – переменная потока.


ThreadLocal и потоконебезопасные обьекты

Одним из важных применений ThreadLocal является работа с потокоНЕбезопасными объектами.

Объекты некоторых классов (например SimpleDateFormat) потокоНЕбезопасны.

То есть если к одному и тому же объекту SimpleDateFormat одновременно обращаются несколько потоков, то нужно применять синхронизацию в потоках (используя synchronized например), иначе будет ошибка. Но синхр-я тормозит работу программы. Поможет ThreadLocal.

То есть если объект реализует Runnable, и он будет использоваться многими потоками, и в этом объекте есть потокоНЕбезопасный объект, лучше не использовать синхронизацию, а размножить его на все потоки используя ThreadLocal.

То есть с помощью ThreadLocal можно сделать так, что у каждого потока будет свой объект SimpleDateFormat.


Дополнительные материалы

Additional Material Icon

Следующие уроки

Fork/Join framework в Java

18
мин.

Similar Articles Icon
Divider

Что такое сериализация в Java

10
мин.

Similar Articles Icon
Divider

Transient в Java

8
мин.

Similar Articles Icon