Создание новых Java-потоков в Message Driven Bean (MDB) - PullRequest
4 голосов
/ 07 июня 2011

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

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

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

Ответы [ 4 ]

2 голосов
/ 07 июня 2011

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

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

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

1 голос
/ 08 июня 2011

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

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

1 голос
/ 07 июня 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 themes .

1 голос
/ 07 июня 2011

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

Корпоративные JavaBeansTM, Версия 3.0, Состояния основных контрактов и требований EJB в разделе 21.1.2 Ограничения на программирование:

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

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

...