Pourquoi la création de threads dans le conteneur Java EE est-elle déconseillée?

120

L'une des premières choses que j'ai apprises sur le développement Java EE est que je ne devrais pas créer mes propres threads dans un conteneur Java EE. Mais quand j'y pense, je ne connais pas la raison.

Pouvez-vous expliquer clairement pourquoi il est découragé?

Je suis sûr que la plupart des applications d'entreprise ont besoin de tâches asynchrones telles que les démons de messagerie, les sessions inactives, les tâches de nettoyage, etc.

Donc, si en effet on ne doit pas générer de threads, quelle est la bonne façon de le faire en cas de besoin?

LiorH
la source
4
Les tâches asynchrones sont généralement effectuées à l'aide de la messagerie JMS et des MDB.
Ken Liu
5
Ce problème devrait bientôt appartenir au passé une fois que JSR 236 sera implémenté dans les conteneurs.
letmaik
5
Cela a été découragé car tous les seconds threads doivent être créés et gérés par le conteneur, afin que le thread ait accès aux autres ressources de l'entreprise. Avec Java EE7, il existe une manière standard et correcte de créer des threads dans un environnement d'entreprise. En utilisant Concurrency Utils, vous vous assurez que votre nouveau thread est créé et géré par le conteneur, garantissant que tous les services EE sont disponibles. Exemple ici
Chris Ritchie
Plusieurs méthodes correctes dans la perspective JSF / EJB peuvent être trouvées ici: stackoverflow.com/q/6149919
BalusC

Réponses:

84

Il est déconseillé car toutes les ressources de l'environnement sont censées être gérées, et potentiellement surveillées, par le serveur. En outre, une grande partie du contexte dans lequel un thread est utilisé est généralement attachée au thread d'exécution lui-même. Si vous démarrez simplement votre propre thread (ce que je crois que certains serveurs ne permettront même pas), il ne pourra pas accéder à d'autres ressources. Cela signifie que vous ne pouvez pas obtenir un InitialContext et effectuer des recherches JNDI pour accéder à d'autres ressources système telles que JMS Connection Factories et Datasources.

Il existe des moyens de le faire «correctement», mais cela dépend de la plate-forme utilisée.

Commonj WorkManager est commun à WebSphere et WebLogic ainsi qu'à d'autres

Plus d'infos ici

Et ici

Reproduit aussi quelque peu celui-ci de ce matin

MISE À JOUR: Veuillez noter que cette question et cette réponse concernent l'état de Java EE en 2009, les choses se sont améliorées depuis!

Robin
la source
1
vous ne pouvez pas obtenir un InitialContext et effectuer des recherches JNDI pour accéder à d'autres ressources système telles que JMS Connection Factories et Datasources. J'ai une application qui fonctionne autour de cela en injectant la source de données lors du démarrage des threads, mais je
devrai
6
Il existe désormais un moyen standard et correct de créer des threads avec l'API Java EE principale. En utilisant Concurrency Utils, vous vous assurez que votre nouveau thread est créé et géré par le conteneur, garantissant que tous les services EE sont disponibles. Exemples ici et ici
Chris Ritchie
@ChrisRitchie merci pour le tuyau. si seulement JBoss AS / IBM WAS prend en charge Java EE 7 ... :-(
asgs
1
@asgs WildFly 8 (nouveau nom pour JBoss AS) prend en charge Java EE 7. IBM n'est que la certification
Chris Ritchie
34

Pour les EJB, ce n'est pas seulement déconseillé, c'est expressément interdit par la spécification :

Un bean entreprise ne doit pas utiliser de primitives de synchronisation de thread pour synchroniser l'exécution de plusieurs instances.

et

Le bean entreprise ne doit pas tenter de gérer les threads. Le bean entreprise ne doit pas tenter de démarrer, arrêter, suspendre ou reprendre un thread, ni changer la priorité ou le nom d'un thread. Le bean entreprise ne doit pas tenter de gérer les groupes de threads.

La raison en est que les EJB sont destinés à fonctionner dans un environnement distribué. Un EJB peut être déplacé d'une machine d'un cluster à une autre. Les threads (et les sockets et autres installations restreintes) sont un obstacle important à cette portabilité.

Dan Dyer
la source
3
Les utilitaires de concurrence Java EE7 fournissent un moyen correct de créer des threads dans un environnement d'entreprise. Exemples ici et ici
Chris Ritchie
1
@Dan Pouvez-vous m'expliquer pourquoi un Thread constituerait un obstacle important à la portabilité du déplacement d'un EJB d'une machine d'une machine à une autre?
Geek
13

La raison pour laquelle vous ne devriez pas générer vos propres threads est que ceux-ci ne seront pas gérés par le conteneur. Le conteneur prend en charge beaucoup de choses qu'un développeur novice peut avoir du mal à imaginer. Par exemple, des opérations telles que le pool de threads, le clustering, les récupérations sur incident sont effectuées par le conteneur. Lorsque vous démarrez un thread, vous risquez de perdre certains d'entre eux. Le conteneur vous permet également de redémarrer votre application sans affecter la JVM sur laquelle elle s'exécute. Comment cela serait-il possible s'il y avait des threads hors du contrôle du conteneur?

C'est la raison pour laquelle des services de minuterie J2EE 1.4 ont été introduits. Consultez cet article pour plus de détails.

kgiannakakis
la source
2
JSR 236 a ajouté des fonctionnalités pour prendre en charge les threads de génération dans Java EE 7 et versions ultérieures. Voir ce frère Réponse de Chris Ritchie .
Basil Bourque
8

Utilitaires de concurrence pour Java EE

Il existe désormais un moyen standard et correct de créer des threads avec l'API Java EE principale:

En utilisant Concurrency Utils, vous vous assurez que votre nouveau thread est créé et géré par le conteneur, garantissant que tous les services EE sont disponibles.

Exemples ici

Chris Ritchie
la source
2

Vous pouvez toujours indiquer au conteneur de démarrer des éléments dans le cadre de vos descripteurs de déploiement. Ceux-ci peuvent alors effectuer toutes les tâches de maintenance dont vous avez besoin.

Suis les règles. Vous serez heureux un jour de l'avoir fait :)

Thorbjørn Ravn Andersen
la source
2

Les threads sont interdits dans les conteneurs Java EE selon les plans. Veuillez vous référer aux plans pour plus d'informations.

Ojitha
la source
2

Il n'y a aucune vraie raison de ne pas le faire. J'ai utilisé Quarz avec Spring dans une application Web sans problème. Le cadre de concurrence java.util.concurrentpeut également être utilisé. Si vous implémentez votre propre gestion des threads, définissez les theads sur deamon ou utilisez un propre groupe de threads Deamon pour que le conteneur puisse décharger votre application Web à tout moment.

Mais attention, la session et la requête bean scopes ne fonctionnent pas dans les threads générés! De plus, les autres codes utilisés ThreadLocalne fonctionnent pas hors de la boîte, vous devez transférer les valeurs aux threads générés par vous-même.

Arne Burmeister
la source
1

Je n'ai jamais lu que c'était découragé, sauf du fait que ce n'est pas facile de le faire correctement.

C'est une programmation de bas niveau, et comme les autres techniques de bas niveau, vous devriez avoir une bonne raison. La plupart des problèmes de concurrence peuvent être résolus beaucoup plus efficacement à l'aide de constructions intégrées telles que les pools de threads.

Levand
la source
7
il est en effet interdit par la spécification.
Ken Liu
1

Une raison que j'ai trouvée si vous générez des threads dans votre EJB et que vous essayez ensuite de décharger le conteneur ou de mettre à jour votre EJB, vous allez rencontrer des problèmes. Il y a presque toujours une autre façon de faire quelque chose où vous n'avez pas besoin d'un fil, alors dites simplement NON.

Javamann
la source