Perché la generazione di thread nel contenitore Java EE è scoraggiata?


120

Una delle prime cose che ho imparato sullo sviluppo di Java EE è che non dovrei generare i miei thread all'interno di un contenitore Java EE. Ma quando ci penso, non ne conosco il motivo.

Puoi spiegare chiaramente perché è scoraggiato?

Sono sicuro che la maggior parte delle applicazioni aziendali necessita di qualche tipo di lavoro asincrono come daemon di posta, sessioni inattive, lavori di pulizia ecc.

Quindi, se davvero non si dovrebbero generare thread, qual è il modo corretto per farlo quando necessario?


4
Le attività asincrone vengono solitamente eseguite utilizzando la messaggistica JMS e gli MDB.
Ken Liu

5
Questo problema dovrebbe presto essere un ricordo del passato una volta che JSR 236 sarà implementato nei container.
letmaik

5
È stato sconsigliato perché eventuali secondi thread dovrebbero essere creati e gestiti dal contenitore, in modo che il thread abbia accesso alle altre risorse dell'organizzazione. Con Java EE7, esiste un modo standard e corretto per creare thread in un ambiente aziendale. Utilizzando Concurrency Utils, ti assicuri che il tuo nuovo thread sia creato e gestito dal contenitore, garantendo che tutti i servizi EE siano disponibili. Esempio qui
Chris Ritchie

Diversi modi corretti in prospettiva JSF / EJB possono essere trovate qui: stackoverflow.com/q/6149919
BalusC

Risposte:


84

È sconsigliato perché tutte le risorse all'interno dell'ambiente devono essere gestite e potenzialmente monitorate dal server. Inoltre, gran parte del contesto in cui viene utilizzato un thread è in genere collegato al thread di esecuzione stesso. Se avvii semplicemente il tuo thread (che credo che alcuni server non consentano nemmeno), non sarà possibile accedere ad altre risorse. Ciò significa che non è possibile ottenere un InitialContext ed eseguire ricerche JNDI per accedere ad altre risorse di sistema come JMS Connection Factories e Datasources.

Ci sono modi per farlo "correttamente", ma dipende dalla piattaforma utilizzata.

Commonj WorkManager è comune a WebSphere e WebLogic e ad altri

Maggiori info qui

E qui

Anche in qualche modo duplica questo di questa mattina

AGGIORNAMENTO: Si prega di notare che questa domanda e risposta si riferiscono allo stato di Java EE nel 2009, le cose sono migliorate da allora!


1
non è possibile ottenere un InitialContext ed eseguire ricerche JNDI per accedere ad altre risorse di sistema come JMS Connection Factories e Datasources. Ho un'app che aggira questo problema iniettando l'origine dati quando si avviano i thread, ma potrei dover ripensare a questo approccio ...
rjohnston

6
Esiste ora un modo standard e corretto per creare thread con l'API Java EE principale. Utilizzando Concurrency Utils, ti assicuri che il tuo nuovo thread sia creato e gestito dal contenitore, garantendo che tutti i servizi EE siano disponibili. Esempi qui e qui
Chris Ritchie

@ChrisRitchie, grazie per il suggerimento. se solo JBoss AS / IBM fosse supportato Java EE 7 ... :-(
asgs

1
@asgs WildFly 8 (nuovo nome per JBoss AS) supporta Java EE 7. IBM è solo certificazione certificata
Chris Ritchie

34

Per i bean EJB, non solo è sconsigliato, ma è espressamente vietato dalle specifiche :

Un bean enterprise non deve utilizzare primitive di sincronizzazione dei thread per sincronizzare l'esecuzione di più istanze.

e

Il bean enterprise non deve tentare di gestire i thread. Il bean enterprise non deve tentare di avviare, arrestare, sospendere o riprendere un thread o di modificare la priorità o il nome di un thread. Il bean enterprise non deve tentare di gestire i gruppi di thread.

Il motivo è che gli EJB devono funzionare in un ambiente distribuito. Un bean potrebbe essere spostato da una macchina in un cluster a un'altra. Thread (e socket e altre strutture limitate) sono un ostacolo significativo a questa portabilità.


3
Java EE7 Concurrency Utils fornisce un modo corretto per creare thread in un ambiente aziendale. Esempi qui e qui
Chris Ritchie

1
@ Dan Puoi spiegarmi perché un Thread sarebbe un ostacolo significativo alla portabilità dello spostamento di un EJB da una macchina in un custer a un'altra?
Geek

13

Il motivo per cui non dovresti generare i tuoi thread è che questi non saranno gestiti dal contenitore. Il contenitore si occupa di molte cose che uno sviluppatore inesperto può trovare difficile immaginare. Ad esempio, cose come il pool di thread, il clustering, i ripristini di arresto anomalo vengono eseguiti dal contenitore. Quando avvii un thread potresti perderne alcuni. Inoltre, il contenitore consente di riavviare l'applicazione senza influire sulla JVM su cui viene eseguita. Come sarebbe possibile se ci fossero thread fuori dal controllo del contenitore?

Questo è il motivo per cui da J2EE 1.4 sono stati introdotti i servizi di timer. Vedi questo articolo per i dettagli.


2
JSR 236 ha aggiunto funzionalità per supportare la generazione di thread in Java EE 7 e versioni successive. Vedi questa risposta del fratello di Chris Ritchie .
Basil Bourque

8

Utilità di concorrenza per Java EE

Ora esiste un modo standard e corretto per creare thread con l'API Java EE principale:

Utilizzando Concurrency Utils, ti assicuri che il tuo nuovo thread sia creato e gestito dal contenitore, garantendo che tutti i servizi EE siano disponibili.

Esempi qui


2

Puoi sempre dire al contenitore di avviare qualcosa come parte dei tuoi descrittori di distribuzione. Questi possono quindi svolgere tutte le attività di manutenzione che devi fare.

Segui le regole. Sarai felice di averlo fatto un giorno :)


2

I thread sono vietati nei contenitori Java EE in base ai modelli. Fare riferimento ai progetti per ulteriori informazioni.


2

Non c'è una vera ragione per non farlo. Ho usato Quarz con Spring in una webapp senza problemi. java.util.concurrentPuò essere utilizzato anche il framework di concorrenza . Se si implementa la propria manipolazione del filo, impostare i theads al demone o utilizzare un proprio gruppo di thread demone per loro in modo che il contenitore può scaricare il vostro webapp in qualsiasi momento.

Ma attenzione, la sessione e la richiesta dei bean scopes non funzionano nei thread generati! Inoltre, altri codici inseriti ThreadLocalnon funzionano immediatamente , è necessario trasferire i valori ai thread generati da soli.


1

Non ho mai letto che sia scoraggiato, tranne per il fatto che non è facile da fare correttamente.

È una programmazione di livello abbastanza basso e, come altre tecniche di basso livello, dovresti avere una buona ragione. La maggior parte dei problemi di concorrenza può essere risolta in modo molto più efficace utilizzando costrutti incorporati come i pool di thread.


7
è infatti vietato dalle specifiche.
Ken Liu

1

Una ragione per cui ho scoperto che se si generano alcuni thread in EJB e poi si tenta di scaricare il contenitore o aggiornare il proprio EJB, si verificano problemi. C'è quasi sempre un altro modo per fare qualcosa in cui non hai bisogno di un thread, quindi dì semplicemente NO.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.