Dlaczego odradza się tworzenie wątków w kontenerze Java EE?

120

Jedną z pierwszych rzeczy, których nauczyłem się o programowaniu Java EE, jest to, że nie powinienem tworzyć własnych wątków w kontenerze Java EE. Ale kiedy o tym myślę, nie znam powodu.

Czy możesz jasno wyjaśnić, dlaczego jest to odradzane?

Jestem pewien, że większość aplikacji korporacyjnych wymaga pewnego rodzaju zadań asynchronicznych, takich jak demony pocztowe, sesje bezczynności, zadania czyszczenia itp.

Jeśli więc rzeczywiście nie powinno się tworzyć wątków, jaki jest właściwy sposób na zrobienie tego w razie potrzeby?

LiorH
źródło
4
Zadania asynchroniczne są zwykle wykonywane przy użyciu przesyłania komunikatów JMS i baz danych MDB.
Ken Liu
5
Ta kwestia wkrótce powinna odejść w przeszłość, gdy JSR 236 zostanie zaimplementowany w kontenerach.
letmaik
5
To był zniechęcony, bo lada chwila wątki powinny być tworzone i zarządzane przez kontener, tak, że wątek będzie miał dostępu do innych zasobów przedsiębiorstwa. Java EE7 zapewnia standardowy i poprawny sposób tworzenia wątków w środowisku przedsiębiorstwa. Używając Concurrency Utils, zapewniasz, że Twój nowy wątek jest tworzony i zarządzany przez kontener, gwarantując, że wszystkie usługi EE są dostępne. Przykład tutaj
Chris Ritchie
Kilka poprawnych sposobów w perspektywie JSF / EJB można znaleźć tutaj: stackoverflow.com/q/6149919
BalusC

Odpowiedzi:

84

Nie jest to zalecane, ponieważ wszystkie zasoby w środowisku mają być zarządzane i potencjalnie monitorowane przez serwer. Ponadto większość kontekstu, w którym używany jest wątek, jest zwykle dołączona do samego wątku wykonania. Jeśli po prostu uruchomisz swój własny wątek (na co uważam, że niektóre serwery nawet nie pozwalają), nie będzie on mógł uzyskać dostępu do innych zasobów. Oznacza to, że nie można uzyskać kontekstu początkowego i wyszukiwać JNDI w celu uzyskania dostępu do innych zasobów systemowych, takich jak fabryki połączeń JMS i źródła danych.

Istnieją sposoby, aby to zrobić „poprawnie”, ale zależy to od używanej platformy.

Wspólny program WorkManager jest wspólny dla produktów WebSphere i WebLogic, a także innych

Więcej informacji tutaj

I tu

Również trochę powiela ten z dzisiejszego ranka

AKTUALIZACJA: Proszę zauważyć, że to pytanie i odpowiedź odnoszą się do stanu Java EE w 2009 roku. Od tego czasu sytuacja się poprawiła!

Rudzik
źródło
1
nie można uzyskać InitialContext i wyszukiwać JNDI w celu uzyskania dostępu do innych zasobów systemowych, takich jak fabryki połączeń JMS i źródła danych. Mam aplikację, która działa wokół tego, wstrzykując źródło danych podczas uruchamiania wątków, ale być może będę musiał przemyśleć to podejście ...
rjohnston
6
Obecnie istnieje standardowy i poprawny sposób tworzenia wątków za pomocą podstawowego interfejsu API Java EE. Używając Concurrency Utils, zapewniasz, że Twój nowy wątek jest tworzony i zarządzany przez kontener, gwarantując, że wszystkie usługi EE są dostępne. Przykłady tu i tutaj
Chris Ritchie,
@ChrisRitchie dzięki za cynk. gdyby tylko JBoss AS / IBM WAS obsługiwał Java EE 7 ... :-(
asgs
1
@asgs JBoss Application Server 8 (nowa nazwa dla JBoss AS) obsługuje Java EE 7. IBM jest tylko Java EE 6 certyfikowane certyfikacja
Chris Ritchie
34

W przypadku EJB jest to nie tylko odradzane, ale wyraźnie zabronione przez specyfikację :

Komponent bean przedsiębiorstwa nie może używać operacji podstawowych synchronizacji wątków do synchronizowania wykonywania wielu instancji.

i

Komponent bean przedsiębiorstwa nie może podejmować prób zarządzania wątkami. Komponent bean przedsiębiorstwa nie może próbować uruchamiać, zatrzymywać, zawieszać ani wznawiać wątku ani zmieniać priorytetu lub nazwy wątku. Komponent bean przedsiębiorstwa nie może podejmować prób zarządzania grupami wątków.

Powodem jest to, że EJB mają działać w środowisku rozproszonym. EJB można przenieść z jednego komputera w klastrze do innego. Wątki (oraz gniazda i inne ograniczone możliwości) stanowią istotną przeszkodę dla tej przenośności.

Dan Dyer
źródło
3
Narzędzia współbieżności Java EE7 zapewniają poprawny sposób tworzenia wątków w środowisku przedsiębiorstwa. Przykłady tu i tutaj
Chris Ritchie,
1
@Dan Czy możesz mi wyjaśnić, dlaczego wątek byłby znaczącą przeszkodą w przenoszeniu EJB z jednej maszyny w klastrze na drugą?
Geek
13

Powodem, dla którego nie powinieneś tworzyć własnych wątków, jest to, że nie będą one zarządzane przez kontener. Kontener zajmuje się wieloma rzeczami, które początkującym programistom mogą być trudne do wyobrażenia. Na przykład takie rzeczy, jak pule wątków, klastrowanie, odzyskiwanie po awarii są wykonywane przez kontener. Kiedy zaczynasz wątek, możesz stracić część z nich. Kontener umożliwia również ponowne uruchomienie aplikacji bez wpływu na maszynę JVM, na której działa. Jak byłoby to możliwe, gdyby były wątki poza kontrolą kontenera?

Z tego powodu od wersji J2EE 1.4 wprowadzono usługi timera. Więcej informacji znajdziesz w tym artykule.

kgiannakakis
źródło
2
JSR 236 dodał funkcje do obsługi tworzenia wątków w Java EE 7 i nowszych. Zobacz odpowiedź dla rodzeństwa autorstwa Chrisa Ritchiego .
Basil Bourque
8

Narzędzia współbieżności dla Java EE

Obecnie istnieje standardowy i poprawny sposób tworzenia wątków za pomocą podstawowego interfejsu API Java EE:

Używając Concurrency Utils, zapewniasz, że Twój nowy wątek jest tworzony i zarządzany przez kontener, gwarantując, że wszystkie usługi EE są dostępne.

Przykłady tutaj

Chris Ritchie
źródło
2

Zawsze możesz powiedzieć kontenerowi, aby zaczął coś w ramach deskryptorów wdrożenia. Mogą one następnie wykonywać wszelkie czynności konserwacyjne, które musisz wykonać.

Postępować zgodnie z zasadami. Będziesz zadowolony któregoś dnia to zrobiłeś :)

Thorbjørn Ravn Andersen
źródło
2

Wątki są zabronione w kontenerach Java EE zgodnie z planami. Więcej informacji można znaleźć w planach .

Ojitha
źródło
2

Nie ma prawdziwego powodu, aby tego nie robić. Kiedyś Quarz z wiosną w webapp bez problemów. Można również java.util.concurrentużyć struktury współbieżności . Jeśli zaimplementować własną obsługę wątków ustaw theads do deamon lub użyć własnej grupy wątek deamon dla nich więc pojemnik może wyładować swoją webapp czasu.

Ale uważaj, sesja bean zakresów i żądanie nie działają w utworzonych wątkach! Również inny kod ThreadLocalnie działa po wyjęciu z pudełka, musisz samodzielnie przenieść wartości do utworzonych wątków.

Arne Burmeister
źródło
1

Nigdy nie czytałem, że to zniechęca, poza tym, że nie jest to łatwe do wykonania poprawnie.

Jest to programowanie dość niskopoziomowe i podobnie jak inne techniki niskiego poziomu powinieneś mieć dobry powód. Większość problemów ze współbieżnością można rozwiązać znacznie efektywniej za pomocą konstrukcji wbudowanych, takich jak pule wątków.

Levand
źródło
7
jest to rzeczywiście zabronione przez specyfikację.
Ken Liu
1

Jeden z powodów, dla których znalazłem, jeśli odrodzisz kilka wątków w swoim EJB, a następnie spróbujesz wyładować kontener lub zaktualizować EJB, napotkasz problemy. Prawie zawsze istnieje inny sposób zrobienia czegoś, w którym nie potrzebujesz wątku, więc po prostu powiedz NIE.

Javamann
źródło