Использование Threadlocal в обратных вызовах

Я читал о классе ThreadLocal, когда несколько раз сталкивался с приведенным ниже заявлением Джошуа Блоха.

«Подтасовка» значений с помощью обратных вызовов, которые вы не контролируете: иногда вы должны вызывать библиотечный метод, который вызывает обратный вызов в вашем пакете. На данный момент вам нужен какой-то контекст, который вы не смогли передать себе из-за недостатков в библиотеке. В этой редкой ситуации локальные переменные потока могут спасти жизнь.

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

Спасибо ..Хина


person HungryForKnowledge    schedule 28.11.2012    source источник
comment
Я думаю, что заголовок вашего вопроса не подходит. Попробуйте изменить его, чтобы уточнить свой вопрос.   -  person Juvanis    schedule 28.11.2012
comment
Локальная переменная потока — это своего рода статическое значение, которое является статическим только в контексте данного потока, поэтому вы можете установить его любым методом, который хотите, а затем прочитать значение в любом другом методе, но в том же потоке выполнения.   -  person damiankolasa    schedule 28.11.2012
comment
@ivanovic Готово.. Надеюсь, теперь это подходит.   -  person HungryForKnowledge    schedule 28.11.2012
comment
@fatfredyy Извините, но как это связано с утверждением, которое я пытаюсь понять.   -  person HungryForKnowledge    schedule 28.11.2012
comment
threadlocal - это локальная переменная, определенная для каждого потока, в некоторых сценариях нам нужно, чтобы потоки несли некоторую информацию, ну, threadlocal - это ответ на этот вопрос, считайте, что это локальная переменная для каждого потока, доступ к которой может получить только поток-владелец   -  person Hussain Akhtar Wahid 'Ghouri'    schedule 28.11.2012
comment
И +1 г-ну Блоху за то, что он придумал термин подлость.   -  person Jo Jo    schedule 06.02.2016


Ответы (2)


Мое приложение вызывает библиотеку, которая ищет сохраненные данные.

Эта библиотека также имеет интерфейс, который вы можете реализовать, который сообщает ей, как преобразовывать необработанные результаты поиска в нужный формат данных.

Моя реализация того, как преобразовать результаты поиска в нужные мне объекты, предполагает знание определенного часового пояса.

Таким образом, процесс таков: (A) я вызываю метод поиска в библиотеке, (B) метод поиска затем вызывает мой другой фрагмент кода, который преобразует необработанные результаты в мой формат, (C) мое преобразование требует знания часового пояса. Проблема заключается в том, как сделать информацию о часовом поясе, которую я знаю в точке А, доступной в точке С?

Очевидно, что методы, предлагаемые библиотекой, не включают передачу часового пояса, поэтому я добавляю его в ThreadLocal!

person Affe    schedule 28.11.2012
comment
Таким образом, недостаток вашей библиотеки заключается в том, что она не включает передачу часового пояса, который нужен вашему общему потоку в (C), а контекст, который вам нужен для себя, - это Threadlocal, содержащий часовой пояс. Таким образом, это означает, что объекты ThreadLocal облегчают/удерживают информация, которая должна быть доступна для других частей приложения. Пожалуйста, поправьте меня, если я ошибаюсь - person HungryForKnowledge; 28.11.2012
comment
Я бы не назвал это недостатком в большинстве случаев, когда это происходит. Если бы каждый фреймворк, предоставляющий точки расширения, предоставлял дополнительные аргументы метода для передачи произвольных данных приложения на разных уровнях контекста один раз за раз, когда вам это нужно... это были бы неприятные API;) - person Affe; 28.11.2012
comment
Бывают также случаи, когда это происходит внутри фреймворков, где что-то запускается обработчиками аннотаций, поэтому не так много практических способов предоставить информацию о времени выполнения. (Глядя на вас JAXB.) - person Affe; 28.11.2012
comment
Согласен :) Но, учитывая утечки, которые переменные ThreadLocal могут опасно вызвать (читайте о сценарии с контейнером Tomcat).. есть ли у нас лучшая альтернатива для этой ситуации? - person HungryForKnowledge; 28.11.2012
comment
Я думаю, что люди слишком параноики, основываясь на одной старой статье, которую парень из IBM написал о том, как их веб-контейнер был дрянным в управлении потоками, и сформулировал это так, как будто это какая-то универсальная истина. Хотя может это только я :) - person Affe; 28.11.2012

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

Что делать?

К сожалению, у вас не так много выбора, кроме как хранить контекст в том, что фактически является глобальной переменной (о ужас!). ThreadLocal — это небольшая доработка глобальной переменной, благодаря которой несколько потоков, использующих этот хак, не будут наступать друг другу на пятки.

Конечно, если обратный вызов происходит в потоке, отличном от того, который вызывает стороннюю функцию, этот метод не работает.

Кроме того, эта техника не масштабируется. Если вы одновременно регистрируете два обратных вызова, вам понадобятся две разные функции обратного вызова и два разных глобальных контекста.

person NPE    schedule 28.11.2012
comment
+1 за указание на проблему с обратными вызовами в разных потоках. Не предоставлять указатель контекста для использования в обратных вызовах просто глупо — вы можете не знать, какой поток будет выполнять обратный вызов, поскольку задачи ставятся в очередь в пул. - person Martin James; 28.11.2012