Чому нерестові потоки в контейнері Java EE не перешкоджають?


120

Одне з перших речей, які я дізнався про розробку Java EE - це те, що я не повинен породити власні потоки всередині контейнера Java EE. Але коли я думаю про це, я не знаю причини.

Чи можете ви чітко пояснити, чому це відлякує?

Я впевнений, що для більшості корпоративних програм потрібні певні асинхронні завдання, такі як демони пошти, непрацюючі сесії, завдання очищення тощо.

Отже, якщо дійсно не слід нерестувати теми, то який це правильний спосіб зробити це за потреби?


4
Асинхронні завдання зазвичай виконуються за допомогою повідомлень JMS та MDB.
Кен Лю

5
Це питання скоро має стати минулим, коли JSR 236 буде впроваджений у контейнери.
letmaik

5
Це було відмовлено, оскільки будь-який другий потік повинен бути створений та керований контейнером, щоб потік мав доступ до інших ресурсів підприємства. Для Java EE7 існує стандартний і правильний спосіб створення ниток у корпоративному середовищі. Використовуючи утиліти Concurrency, ви гарантуєте, що ваш новий потік створений та керується контейнером, гарантуючи, що всі послуги EE доступні. Приклад тут
Кріс Річі

Кілька правильних шляхів в JSF / EJB точки зору можна знайти тут: stackoverflow.com/q/6149919
BalusC

Відповіді:


84

Це не відлякує, оскільки всі ресурси в оточенні повинні управлятися сервером і потенційно контролюватися ним. Крім того, значна частина контексту, в якому використовується нитка, зазвичай додається до самого потоку виконання. Якщо просто запустити власну нитку (яку я вважаю, деякі сервери навіть не дозволять), вона не може отримати доступ до інших ресурсів. Це означає, що ви не можете отримати InitialContext і не шукати JNDI для доступу до інших системних ресурсів, таких як Фабрики підключення JMS та джерела даних.

Існують способи зробити це «правильно», але це залежить від використовуваної платформи.

Commonj WorkManager є загальним для WebSphere та WebLogic, а також інших

Більше інформації тут

І ось тут

Також дещо копіює цей з цього ранку

ОНОВЛЕННЯ: Зверніть увагу, що це питання та відповідь стосуються стану Java EE у 2009 році, з цього часу все покращилось!


1
ви не можете отримати InitialContext і робити пошук JNDI для доступу до інших системних ресурсів, таких як Фабрики підключення JMS та джерела даних. У мене є додаток, який працює над цим, вводячи джерело даних під час запуску потоків, але мені, можливо, доведеться переосмислити цей підхід ...
rjohnston,

6
Зараз існує стандартний і правильний спосіб створення потоків за допомогою основного API Java EE. Використовуючи утиліти Concurrency, ви гарантуєте, що ваш новий потік створений та керується контейнером, гарантуючи, що всі послуги EE доступні. Приклади тут і тут
Кріс Річі

@ChrisRitchie дякую за пораду. якщо тільки JBoss AS / IBM WAS підтримував Java EE 7 ... :-(
asgs

1
@asgs WildFly 8 (нова назва для JBoss AS) робить підтримку Java EE 7. IBM тільки Java EE 6 сертифікованої сертифікація
Кріс Річчі

34

Для EJB це не тільки відлякує, це прямо заборонено специфікацією :

Бін підприємства не повинен використовувати примітиви синхронізації потоків для синхронізації виконання декількох екземплярів.

і

Бін підприємства не повинен намагатися керувати потоками. Компонент підприємства не повинен намагатися запустити, зупинити, призупинити чи відновити потік або змінити пріоритет або ім'я потоку. Бін підприємства не повинен намагатися керувати групами потоків.

Причина полягає в тому, що EJB призначені для роботи в розподіленому середовищі. EJB може бути переміщено з однієї машини в кластер на іншу. Нитки (і розетки та інші обмежені засоби) є суттєвим бар'єром на шляху до цієї мобільності.


3
Конкурсні утиліти Java EE7 забезпечують правильний спосіб створення ниток у корпоративному середовищі. Приклади тут і тут
Кріс Річі

1
@Dan Чи можете ви пояснити мені, чому Нитка буде суттєвим бар'єром для переносимості переміщення EJB з однієї машини в кастер до іншої?
Geek

13

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

Це було причиною того, що з сервісу таймерів J2EE 1.4 було представлено. Детальну інформацію див. У цій статті.


2
JSR 236 додав функції для підтримки нерестових потоків у Java EE 7 та новіших версіях. Дивіться цей відповідь брата та сестри Кріса Річі .
Василь Бурк

8

Утиліти одночасності для Java EE

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

Використовуючи утиліти Concurrency, ви гарантуєте, що ваш новий потік створений та керується контейнером, гарантуючи, що всі послуги EE доступні.

Приклади тут


2

Ви завжди можете сказати контейнеру починати те, що є частиною дескрипторів розгортання. Потім вони можуть виконувати будь-які завдання з обслуговування, які вам потрібно зробити.

Дотримуйся правил. Ви будете раді одного дня ви :)


2

Нитки заборонені в контейнерах Java EE відповідно до креслення. Для отримання додаткової інформації зверніться до креслення .


2

Немає реальної причини не робити цього. Я без проблем використовував кварц з Spring в webapp. Також java.util.concurrentможе використовуватися рамка одночасності . Якщо ви реалізуєте власну обробку ниток, встановіть для thead deamon або використовувати власну групу Deamon нитки для них , так що контейнер може вивантажити ваш веб - додатки в будь-який час.

Але будьте обережні, сеанс роботи з квасолею та прохання не працюють в нитках, що породилися! Крім того, інший код, на ThreadLocalякому розміщено, не працює з поля, вам потрібно перенести значення в породжені нитки самостійно.


1

Я ніколи не читав, що це відлякує, за винятком того, що це зробити непросто правильно.

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


7
це дійсно заборонено спец.
Кен Лю

1

Я знайшов одну з причин, якщо ви створили кілька потоків у вас EJB, а потім намагаєтесь контейнер вивантажити або оновити свій EJB, у вас виникнуть проблеми. Майже завжди є інший спосіб зробити щось там, де вам не потрібна нитка, тому просто скажіть "НІ".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.