локальные переменные потока в сервлете

Являются ли переменные threadlocals глобальными для всех запросов к сервлету, которому принадлежат эти переменные?

Я использую смолу для сервера.

Спасибо за авзер.

Я думаю, что я могу сделать себя более ясным.

Конкретный случай:

Я хочу:

  • инициализировать статическую переменную, когда запрос начинает выполнение.
  • иметь возможность запрашивать значение переменной при дальнейшем выполнении методов, вызываемых из сервлета, в потокобезопасном режиме, пока запрос не завершит выполнение

person user2427    schedule 26.11.2008    source источник


Ответы (5)


Краткий ответ: да.
Немного более длинный: вот как Spring творит свое волшебство. См. RequestContextHolder (через докжар).

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

Или вы могли бы просто использовать Spring...

person Ran Biron    schedule 17.12.2008

Я думаю, что они являются глобальными для всех запросов, сделанных только с этим конкретным потоком. Другие потоки получают другие копии данных local-thread. Это ключевой момент локального хранилища потока: http://en.wikipedia.org/wiki/Thread-local_storage#Java.

Если вы не отметите соответствующую опцию в конфигурации сервлетов, контейнер сервлетов будет использовать ваш сервлет с несколькими потоками для параллельной обработки запросов. Таким образом, у вас будут отдельные данные для каждого потока, обслуживающего клиентов.

Если ваше веб-приложение не является распределенным (работает на нескольких виртуальных машинах Java), вы можете использовать объект ServletContext для хранения общих данных между запросами и потоками (в этом случае обязательно выполните правильную блокировку).

person Johannes Schaub - litb    schedule 26.11.2008
comment
Верно. В предыдущем проекте я сохранил билет пользователя в его сеансе и создал фильтр для передачи билета из сеанса в локальный поток, чтобы убедиться, что состояние аутентификации пользователя всегда доступно потоку, обрабатывающему запрос. - person Julie; 26.11.2008

Как говорит Адиэль, правильный способ сделать это, вероятно, состоит в том, чтобы использовать контекст запроса (например, HttpServletRequest), а не создавать ThreadLocal. Хотя здесь, безусловно, можно использовать ThreadLocal, вы должны быть осторожны, чтобы очистить свой поток, если вы это сделаете, поскольку в противном случае следующий запрос, который получает поток, увидит значение, связанное с предыдущим запросом. (Когда первый запрос будет выполнен с потоком, поток вернется в пул, и поэтому следующий запрос увидит его.) Нет причин управлять такими вещами, когда контекст запроса существует именно для этой цели.

person Community    schedule 17.12.2008
comment
Вы также можете использовать фильтр сервлета для управления ThreadLocal, по крайней мере, создание/очистка будет в одном месте. - person sehugg; 11.06.2009
comment
-1 определенно есть веская причина для управления такими вещами, есть разница между передачей аргумента 1000 раз вокруг вашего приложения по сравнению с одним статическим геттером ;-) - person peenut; 22.02.2013
comment
Я не понимаю вашего комментария. Мой ответ не имеет ничего общего ни с передачей аргумента около 1000 раз, ни со статическим геттером. Вместо этого речь идет о выборе между использованием хранилища ThreadLocal и HttpServletRequest в качестве контекста для HTTP-запросов. Учитывая, что OP хочет, чтобы привязки сохранялись на протяжении всего запроса, правильным контекстом является HSR (жизненный цикл совпадает с запросом), а не ThreadLocal (общий для запросов, поскольку рабочие потоки обычно объединяются). HSR позволяет избежать очистки контекста, поскольку он отбрасывается в конце запроса. - person ; 23.02.2013

Использование ThreadLocal для хранения информации области запроса может привести к сбою, если вы используете Servlet 3.0 Susppendable Requests (или Jetty Continuations). Использование нескольких потоков этого API обрабатывает один запрос.

person Chris    schedule 03.06.2014

Локальные переменные Threadlocal всегда определены для глобального доступа, поскольку суть заключается в прозрачной передаче информации по системе, к которой можно получить доступ из любого места. Значение переменной привязано к потоку, в котором оно установлено, поэтому, хотя переменная является глобальной, она может иметь разные значения в зависимости от потока, из которого к ней обращаются.

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

person Robin    schedule 26.11.2008