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

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

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

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

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

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

class SomeThread implements Runnable { // локальная переменная объекта класса int counter; // локальная переменная потока ThreadLocal threadLocalCounter = new ThreadLocal<>(); // то есть, как видим, есть переменные ОБЪЕКТА, // а есть переменные ПОТОКА. // Смотри более подробно после кода public void run() { counter++; if (threadLocalCounter.get() != null) { // запись в переменную ThreadLocal // через метод set threadLocalCounter.set(threadLocalCounter.get() + 1); } else { threadLocalCounter.set(0); } System.out.println(“Counter: ” + counter); System.out.println(“threadLocalCounter: ” + threadLocalCounter.get()); } } class ThreadLocalExample { public static void main(String[] args) { SomeThread threadDemo = new SomeThread(); Thread t1 = new Thread(threadDemo); Thread t2 = new Thread(threadDemo); Thread t3 = new Thread(threadDemo); t1.start(); try { Thread.sleep(200); } catch (InterruptedException e) {} t2.start(); try { Thread.sleep(200); } catch (InterruptedException e) {} t3.start(); } }

Вывод:

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

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

Search Icon

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


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

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

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

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

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

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

Fork/Join framework в Java

Fork/Join Framework в Java: разбивайте задачи на подзадачи для параллельного выполнения. Пример использования RecursiveTask и оптимизация многопоточных вычислений.

Time to read: 18

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

Узнайте, как работает сериализация в Java: сохраняйте объекты в файлы с ObjectOutputStream и восстанавливайте их через ObjectInputStream. Пример кода и важность интерфейса Serializable.

Time to read: 10

Transient в Java

Ключевое слово transient в Java: как исключить поля из сериализации. Практическое руководство по работе с несериализуемыми данными.

Time to read: 8