2009-02-10 5 views
108

L'une des premières choses que j'ai apprises au sujet du développement de Java EE est que je ne devrais pas générer mes propres threads dans un conteneur Java EE. Mais quand j'y pense, je ne connais pas la raison.Pourquoi les threads spawning dans le conteneur Java EE sont-ils déconseillés?

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

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

Ainsi, si en effet on ne doit pas engendrer des fils, ce qui est la bonne façon de le faire si nécessaire?

+4

tâches asynchrones sont généralement effectués en utilisant la messagerie JMS et BDM. –

+5

Ce problème devrait bientôt faire partie du passé [JSR 236] (http://jcp.org/fr/jsr/detail?id=236) implémenté dans les conteneurs. – letmaik

+4

Il a été déconseillé car tout second thread doit être créé et géré par le conteneur, afin que le thread puisse accéder aux autres ressources de l'entreprise. Avec Java EE7, il existe un moyen standard et correct 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] (http: // stackoverflow.com/questions/3212255/java-ee-spécification-et-multi-threading/19404307 # 19404307) –

Répondre

79

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é au thread d'exécution lui-même. Si vous lancez simplement votre propre thread (ce que je crois que certains serveurs ne permettent même pas), il ne peut pas accéder à d'autres ressources. Cela signifie que vous ne pouvez pas obtenir de requêtes InitialContext et JNDI pour accéder à d'autres ressources système telles que les fabriques de connexions 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.

The commonj WorkManager is common for WebSphere and WebLogic as well as others

More info here

And here

également fait double emploi avec un peu this one ce matin

MISE À JOUR: S'il vous plaît noter que cette question et la réponse se rapportent à l'état de Java EE en 2009, les choses ont amélioré depuis lors!

+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 contourne cela en injectant la source de données au démarrage des threads, mais je devrais repenser cette approche. .. – rjohnston

+6

Il existe maintenant 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] (http://blog.chris-ritchie.com/2013/09/simple-concurrency-example-with-wildfly.html) et [ici] (http: //blog.chris-ritchie. com/2013/10/géré-fil-usine-exemple-en-wildfly.html) –

+0

@ChrisRitchie merci pour le conseil. si seulement JBoss AS/IBM était supporté Java EE 7 ... :-( – asgs

1

Je n'ai jamais lu que c'est découragé, sauf du fait que ce n'est pas facile à 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 concurrence peuvent être résolus beaucoup plus efficacement en utilisant des constructions intégrées comme des pools de threads.

+7

il est en effet interdit par la spécification. –

+0

http://java.dzone.com/articles/5-quick-points-about-threads – newday

11

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 soin de beaucoup de choses qu'un développeur novice peut trouver difficile à imaginer. Par exemple, des choses comme le regroupement de threads, la mise en cluster, les récupérations après 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 il est exécuté. Comment cela serait-il possible s'il y avait des threads hors du contrôle du conteneur?

C'est la raison pour laquelle les services de minuterie J2EE 1.4 ont été introduits. Voir article this pour plus de détails.

+1

JSR 236 a ajouté des fonctionnalités pour prendre en charge les threads de spawning dans Java EE 7 et versions ultérieures. Voir [ce frère Répondre par Chris Ritchie] (http://stackoverflow.com/a/19404453/642706). –

2

Il n'y a pas de véritable raison de ne pas le faire. J'ai utilisé Quarz avec Spring dans une webapp sans problèmes. Le cadre de concurrence simultanée java.util.concurrent peut également être utilisé. Si vous implémentez votre propre gestion de thread, définissez les theads sur deamon ou utilisez un groupe de threads deamon pour eux afin que le conteneur puisse décharger votre application Web à tout moment.

Mais attention, les champs d'application de haricots session de et demande ne fonctionnent pas dans les discussions donné naissance!Également un autre code publié sur ThreadLocal ne fonctionne pas de la boîte, vous devez transférer les valeurs aux threads générés par vous-même.

2

Vous pouvez toujours demander au conteneur de démarrer des éléments dans le cadre de vos descripteurs de déploiement. Ceux-ci peuvent alors faire toutes les tâches de maintenance que vous devez faire.

Suivez les règles. Vous serez heureux un jour que vous l'avez fait :)

0

Une raison que j'ai trouvée si vous avez engendré des threads dans votre EJB et que vous essayez de faire décharger ou 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.

32

Pour EJBs, il est non seulement découragée, il est expressément interdit par le specification:

Un haricot d'entreprise ne doit pas utiliser les primitives de synchronisation fil à synchroniser l'exécution de plusieurs instances .

et

Le haricot de l'entreprise ne doit pas tenter de gérer threads. Le bean entreprise ne doit pas tenter de démarrer, arrêter, suspendre ou reprendre un fil, ou changer la priorité ou le nom d'un fil. Le bean enterprise 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 dans un cluster à un autre. Les threads (et les sockets et autres équipements restreints) constituent un obstacle important à cette portabilité.

+3

Les utilitaires de concordance Java EE7 fournissent un moyen correct de créer des unités d'exécution dans un environnement d'entreprise: Exemples [ici] (http: // blog.chris-ritchie.com/2013/09/simple-concurrency-example-with-wildfly.html) et [ici] (http://blog.chris-ritchie.com/2013/10/managed-thread-factory -exemple-dans-wildfly.html) –

+1

@ Dan Pouvez-vous m'expliquer pourquoi un Thread serait un obstacle important à la portabilité de déplacer un EJB d'une machine dans un custer à un autre? – Geek

2

Les fils sont interdits dans les conteneurs Java EE conformément aux plans. Veuillez vous référer au blueprints pour plus d'informations.

5

Concurrency Utilities pour Java EE

Il y a maintenant une norme et bonne façon de créer des threads avec le noyau API Java 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 here