Если вы читаете эту статью, вы должны иметь базовое представление о концепции потоков. Если нет, не волнуйтесь, вы можете прочитать мою предыдущую статью



Теперь, когда мы знаем о потоках и о том, как их создавать, мы можем изучить некоторые термины, используемые в концепции потоков. Один из них — ThreadLocal.

В чем польза ThreadLocal?

Когда я изучил концепцию Threads, я начал ее использовать. У меня возникла ситуация, когда я создаю веб-приложение и использовал эту концепцию потока для извлечения данных клиента из базы данных.

У меня есть несколько клиентов, и мне нужно получить только данные, специфичные для клиента. Для этого мне нужна переменная или объект, который может содержать данные, специфичные для клиента, и мы также знаем, что данные каждого клиента извлекаются в каждом потоке.

Теперь у меня есть мысль, что я могу создать объект, специфичный для потока. А вот и концепция ThreadLocal

Способ создания объекта ThreadLocal:

ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();

Здесь я упомянул Integer, так как мне нужно целочисленное значение. Вы можете указать тип данных в зависимости от ваших потребностей.

Теперь, когда объект создан, я хочу сохранить значение, характерное для моего потока.

threadLocalValue.set(5);

Метод set устанавливает значение threadlocal равным 5, которое внутренне сохраняет значение в виде карты, где ключом является поток, а значение равно 5.

Мы получаем значение следующим образом.

Integer result = threadLocalValue.get();

Мы также можем инициировать значение ThreadLocal, используя статический метод. Здесь создается экземпляр threadlocal с начальным значением 1.

ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);

Мы также можем удалить значение

threadLocal.remove();

Теперь, когда мы все знаем о ThreadLocal, давайте подумаем о сценариях, в которых он вызывает проблему.

У меня есть ThreadPool, где каждый поток назначается клиенту для получения его данных и назначается ThreadLocal. Идеальный!!

Что, если мой поток завершит работу с данными клиента и вернется в пул потоков и подберет другие данные клиента, а предыдущие данные все еще останутся, если мы не сотрем данные должным образом.

Это приведет к проблеме.

Решение для этого, чтобы убедиться, что мы стираем данные, введенные в ThreadLocal потоком, использует метод afterExecute()

public class ThreadLocalAwareThreadPool extends ThreadPoolExecutor {         
   @Override     
   protected void afterExecute(Runnable r, Throwable t) {         
       // Call remove on each ThreadLocal     
   } 
}

Чтобы использовать метод, мы должны расширить класс ThreadPoolExecutor, который будет выполняться, когда поток будет возвращен в пул потоков.

Большой!!! Надеюсь, вам все ясно с этой концепцией.