Почему не рекомендуется создавать потоки в контейнере Java EE?

Первое, что я узнал о разработке Java EE, это то, что я не должен создавать свои собственные потоки внутри контейнера Java EE. Но когда я думаю об этом, я не знаю причину.

Можете ли вы четко объяснить, почему это не рекомендуется?

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

Итак, если на самом деле не следует создавать потоки, каков правильный способ сделать это при необходимости?

9 ответов

Решение

Это не рекомендуется, поскольку все ресурсы в среде предназначены для управления и потенциального мониторинга сервером. Кроме того, большая часть контекста, в котором используется поток, обычно присоединяется к самому потоку выполнения. Если вы просто запустите свой собственный поток (который, я считаю, некоторые серверы даже не разрешат), он не сможет получить доступ к другим ресурсам. Это означает, что вы не можете получить InitialContext и выполнить поиск JNDI для доступа к другим системным ресурсам, таким как фабрики соединений JMS и источники данных.

Есть способы сделать это "правильно", но это зависит от используемой платформы.

Commonj WorkManager является общим для WebSphere и WebLogic, а также для других

Больше информации здесь

И здесь

Также несколько дублирует этот с утра

ОБНОВЛЕНИЕ: Обратите внимание, что этот вопрос и ответ относятся к состоянию Java EE в 2009 году, с тех пор ситуация улучшилась!

Для EJB это не только не рекомендуется, но и прямо запрещено спецификацией:

Корпоративный компонент не должен использовать примитивы синхронизации потоков для синхронизации выполнения нескольких экземпляров.

а также

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

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

Причина, по которой вы не должны создавать свои собственные потоки, заключается в том, что они не будут управляться контейнером. Контейнер заботится о многих вещах, которые начинающему разработчику трудно найти. Например, такие вещи как пул потоков, кластеризация, восстановление после сбоя выполняются контейнером. Когда вы начинаете тему, вы можете потерять некоторые из них. Кроме того, контейнер позволяет перезапустить приложение, не влияя на JVM, на которой оно выполняется. Как это было бы возможно, если есть потоки из-под контроля контейнера?

Это причина того, что из J2EE 1.4 были введены таймерные сервисы. Смотрите эту статью для деталей.

Утилиты параллелизма для Java EE

Теперь существует стандартный и правильный способ создания потоков с помощью основного Java EE API:

Используя Concurrency Utils, вы гарантируете, что ваш новый поток создан и управляется контейнером, гарантируя, что все службы EE доступны.

Примеры здесь

Нет реальной причины не делать этого. Я использовал Quarz с Spring в веб-приложении без проблем. Также структура параллелизма java.util.concurrent может быть использовано. Если вы реализуете свою собственную обработку потоков, установите для theads значение deamon или используйте для них собственную группу потоков deamon, чтобы контейнер мог выгрузить ваше веб-приложение в любое время.

Но будьте осторожны, сеанс и запрос bean-областей не работают в порожденных потоках! Также другой код сделан на ThreadLocalне работает "из коробки", вам нужно передать значения в порожденные потоки самостоятельно.

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

Следовать правилам. Вы будете рады, что когда-нибудь вы сделали:)

Потоки запрещены в контейнерах Java EE в соответствии с чертежами. Пожалуйста, обратитесь к чертежам для получения дополнительной информации.

Я нашел одну причину, если вы порождаете некоторые потоки в вашем EJB, а затем пытаетесь выгрузить контейнер или обновить свой EJB, у вас возникнут проблемы. Почти всегда есть другой способ сделать что-то, где вам не нужен поток, поэтому просто скажите НЕТ.

Я никогда не читал, что это обескураживает, за исключением того, что это не так просто сделать правильно.

Это довольно низкоуровневое программирование, и, как и другие низкоуровневые методы, у вас должна быть веская причина. Большинство проблем параллелизма можно решить гораздо эффективнее, используя встроенные конструкции, такие как пулы потоков.

Другие вопросы по тегам