web-dev-qa-db-fra.com

Pourquoi la génération de threads dans le conteneur Java EE est déconseillée?

L'une des premières choses que j'ai apprises sur le développement Java EE est que je ne devrais pas générer mes propres threads dans un conteneur Java EE. Mais quand je en y réfléchissant, je ne connais pas la raison.

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

Je suis sûr que la plupart des applications d'entreprise ont besoin d'une sorte de travaux asynchrones comme les démons de messagerie, les sessions inactives, les travaux de nettoyage, etc.

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

118
LiorH

Il est déconseillé car toutes les ressources de l'environnement sont destiné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é au thread d'exécution lui-même. Si vous démarrez simplement votre propre thread (que je crois que certains serveurs ne permettront même pas), il ne peut 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 les usines de connexion JMS et les sources de données.

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

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

Plus d'infos ici

Et ici

Duplique également un peu celui-ci de ce matin

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

84
Robin

Pour les EJB, ce n'est pas seulement découragé, 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 modifier 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 à un autre. Les threads (et les sockets et autres installations restreintes) constituent un obstacle important à cette portabilité.

34
Dan Dyer

La raison pour laquelle vous ne devez 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 de nombreuses choses qu'un développeur novice peut difficilement imaginer. Par exemple, des choses comme 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 pouvez en perdre certains. Le conteneur vous permet également de redémarrer votre application sans affecter la machine virtuelle Java 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 temporisation J2EE 1.4 ont été introduits. Voir cet article pour plus de détails.

13
kgiannakakis

Utilitaires de concurrence pour Java EE

Il existe désormais une méthode standard et correcte pour créer des threads avec le noyau Java API EE:

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

7
Chris Ritchie

Il n'y a aucune vraie raison de ne pas le faire. J'ai utilisé Quarz avec Spring dans une webapp sans problème. Le cadre d'accès simultané Java.util.concurrent peut être utilisé. Si vous implémentez votre propre gestion des threads, définissez les theads sur deamon ou utilisez un propre groupe de threads pour eux afin que le conteneur puisse décharger votre webapp à tout moment.

Mais attention, les sessions de session de bean et requête ne fonctionnent pas dans les fils sont apparus! De plus, un autre code a cessé de fonctionner ThreadLocal ne fonctionne pas, vous devez transférer vous-même les valeurs dans les threads générés.

2
Arne Burmeister

Vous pouvez toujours dire 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 :)

2

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

2
Ojitha

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.

1
Javamann

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

Il s'agit d'une programmation de bas niveau et, comme d'autres techniques de bas niveau, vous devriez avoir une bonne raison. La plupart des problèmes de simultanéité peuvent être résolus beaucoup plus efficacement en utilisant des constructions intégrées comme des pools de threads.

1
levand