Создание новых java-потоков в Message Driven Bean (MDB)

Могу ли я запустить/породить новый поток Java из MDB? У меня есть требование выполнить некоторую параллельную обработку кода в MDB, а затем вернуть управление обратно в MDB.

Требование: Сообщение приходит в MDB, затем выполняется некоторая обработка кода. Затем запускаются два новых подчиненных потока, которые выполняют некоторую параллельную работу. А пока MDB ждет. когда потоки закончат работу. Затем управление возвращается обратно в MDB, который завершает соответствующую окончательную работу/очистку.

Это хорошая идея, чтобы начать новый поток (Runnable) из MDB? Если нет, то какой должна быть альтернатива?


person James Cooper    schedule 07.06.2011    source источник
comment
Мой вопрос: какова будет реальная работа, которую вы хотите выполнять параллельно (двумя подчиненными потоками)? Кроме того, сообщения обрабатываются параллельно, не так ли?   -  person bpgergo    schedule 07.06.2011
comment
@bpgergo . У меня есть отдельный класс процессоров сторонних производителей. Я хочу использовать этот класс в отдельных потоках. Просто рассматривайте этот основной MDB как простой класс Java, только средство для получения сообщения от JMS, а затем действуйте как POJO. Разве план Java-приложения не нуждается в запуске нескольких потоков?   -  person James Cooper    schedule 07.06.2011


Ответы (4)


Запуск новых потоков в MDB — плохая практика. Это будет работать, но новые потоки не контролируют контейнер приложения, поэтому могут вести себя непредсказуемо. Они могут даже испортить управление потоками, которое контейнер пытается поддерживать. Хуже всего то, что если приложение развернуто в кластере, то пользовательские потоки с треском провалятся.

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

person supernova    schedule 08.06.2011

Это плохая идея, если вы выполняете транзакционную работу в потоках.

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

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

person Vineet Reynolds    schedule 07.06.2011
comment
OP не упомянул, что дочерние потоки попытаются получить доступ к транзакционному ресурсу. - person bpgergo; 07.06.2011
comment
@Vineet Спасибо. Я не собираюсь использовать этот MDB в транзакции, но порождаю два потока, а тем временем пусть ждет MDB для завершения потоков. - person James Cooper; 07.06.2011
comment
@bpgergo, обычно это несущественно. Спецификация EJB осуждает запуск потоков, но люди не знают почему. Я попытался изложить наиболее правдоподобное объяснение. - person Vineet Reynolds; 07.06.2011
comment
Если не нить, то должна быть какая-то альтернатива! Отправить управление какой-нибудь другой MDB? Но тогда возникает вопрос, как управление вернется обратно в основной MDB? - person James Cooper; 07.06.2011
comment
@Vineet Reynolds, я тоже хмурюсь, но мне также любопытно, что ОП хочет делать в тредах. - person bpgergo; 07.06.2011
comment
@Джеймс, если ты уверен в том, что делаешь, то обязательно продолжай и делай это. Я хотел бы отметить, что чтение сообщения из очереди/темы — это транзакционная активность, которая фиксируется только в том случае, если MDB успешно обрабатывает сообщение; сообщение хорошо и действительно удаляется из очереди/темы, только если транзакция фиксируется. Любые исключения должны быть тщательно обработаны. - person Vineet Reynolds; 07.06.2011

Запуск потока из MDB нарушает спецификацию.

Enterprise JavaBeansTM, версия 3.0, Основные контракты и требования EJB указаны в разделе 21.1.2 Ограничения по программированию:

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

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

person Kaj    schedule 07.06.2011
comment
спасибо Но тогда какой должна быть альтернатива? - person James Cooper; 07.06.2011
comment
@James Cooper: получение и обработка сообщений из очереди уже параллельны, не так ли? Так что структурируйте свои сообщения так, как одно сообщение —> одна цепочка. - person bpgergo; 07.06.2011

Вы в корне упускаете суть Java EE и MDB.

Контейнер Java EE — это управляемая среда выполнения. Основная идея контейнера Java EE заключается в том, что, делегируя определенные ортогональные задачи, такие как управление транзакциями, контейнеру, компонент остается сосредоточенным на бизнес-логике и (в утопии) является повторно используемым компонентом, который делает мало предположений о своей среде выполнения.

До MDB контейнер Java EE был пассивно-реактивной системой, которая не позволяла координировать действия асинхронных активных агентов на стороне контейнера. Затем Message Driven Beans решили эту проблему, предоставив вам стандартный способ запустить асинхронное действие на стороне сервера.

У вас есть исходное событие e0, которое используется MBD0. В сообщении MDB0 сгенерирует e1 и поставит в очередь сообщение в ответ на MBD1, которое затем выполнит свою работу и отправит сообщение MDB2 и т. д.

У вас есть простой рабочий процесс из n последовательных шагов с использованием семантики обмена сообщениями pub/sub (и o/c с асинхронной семантикой), и все вовлеченные потоки управляются контейнером. Если вы хотите, чтобы участники одновременно работали, а затем собирали результаты и запускали финальное действие, рассмотрите возможность использования шаблонов, включающих темы JMS.

person alphazero    schedule 07.06.2011
comment
спасибо Да, я хочу собрать информацию из всех потоков в конце в основной MDB. Даже, как вы упомянули, если вместо потоков я запускаю пул новых MDB. Тогда как основная MDB будет ждать окончательного собранного результата? Можете ли вы уточнить свои слова, рассмотрите возможность использования шаблонов, связанных с темами JMS... как реализовать этот шаблон? - person James Cooper; 07.06.2011
comment
Тема — задание, а записи — по шагам. Ваш последний bean-компонент будет получать уведомления до тех пор, пока не получит сообщение о последнем шаге, в котором говорится, что вот статус задания, и результаты будут получены. - person alphazero; 18.06.2011