Por que os spawning threads no contêiner Java EE são desencorajados?


120

Uma das primeiras coisas que aprendi sobre o desenvolvimento do Java EE é que não devo gerar meus próprios threads dentro de um contêiner do Java EE. Mas quando penso nisso, não sei o motivo.

Você pode explicar claramente por que isso é desencorajado?

Tenho certeza de que a maioria dos aplicativos corporativos precisa de algum tipo de trabalho assíncrono, como daemons de correio, sessões inativas, trabalhos de limpeza etc.

Portanto, se de fato não se deve gerar tópicos, qual é a maneira correta de fazer isso quando necessário?


4
Tarefas assíncronas geralmente são executadas usando o sistema de mensagens JMS e MDBs.
Ken Liu

5
Esse problema deve em breve ser uma coisa do passado, quando o JSR 236 for implementado nos contêineres.
Letmaik

5
Ele foi desencorajado porque qualquer segunda roscas devem ser criados e gerenciados pelo contêiner, para que o segmento terá acesso a outros recursos da empresa. Com o Java EE7, existe uma maneira padrão e correta de criar encadeamentos em um ambiente corporativo. Ao usar o Concurrency Utils, você garante que seu novo encadeamento seja criado e gerenciado pelo contêiner, garantindo que todos os serviços de EE estejam disponíveis. Exemplo aqui
Chris Ritchie

Várias maneiras corretas na perspectiva JSF / EJB podem ser encontradas aqui: stackoverflow.com/q/6149919
BalusC /

Respostas:


84

É desencorajado porque todos os recursos no ambiente devem ser gerenciados e potencialmente monitorados pelo servidor. Além disso, grande parte do contexto em que um encadeamento está sendo usado é normalmente anexada ao encadeamento de execução em si. Se você simplesmente iniciar seu próprio thread (que eu acredito que alguns servidores nem mesmo permitirão), ele não poderá acessar outros recursos. O que isso significa é que você não pode obter um InitialContext e fazer pesquisas JNDI para acessar outros recursos do sistema, como JMS Connection Factories e Fontes de Dados.

Existem maneiras de fazer isso "corretamente", mas isso depende da plataforma que está sendo usada.

O commonj WorkManager é comum para WebSphere e WebLogic, além de outros

Mais informações aqui

E aqui

Também um pouco duplica este desta manhã

ATUALIZAÇÃO: Observe que esta pergunta e resposta estão relacionadas ao estado do Java EE em 2009; as coisas melhoraram desde então!


1
você não pode obter um InitialContext e fazer pesquisas JNDI para acessar outros recursos do sistema, como Fábricas de Conexão JMS e Fontes de Dados. Eu tenho um aplicativo que funciona em torno desta injetando a fonte de dados ao iniciar os fios, mas eu poderia ter de repensar esta abordagem ...
rjohnston

6
Agora existe uma maneira padrão e correta de criar encadeamentos com a API Java EE principal. Ao usar o Concurrency Utils, você garante que seu novo encadeamento seja criado e gerenciado pelo contêiner, garantindo que todos os serviços de EE estejam disponíveis. Exemplos aqui e aqui
Chris Ritchie

@ Chrishritchie obrigado pela dica. Se apenas JBoss AS / IBM foi apoiado Java EE 7 ... :-(
ASGs

1
@asgs JBoss Application Server 8 (novo nome para JBoss AS) suporta Java EE 7. IBM só é Java EE 6 certificado de certificação
Chris Ritchie

34

Para os EJBs, isso não é apenas desencorajado, é expressamente proibido pela especificação :

Um enterprise bean não deve usar primitivas de sincronização de encadeamentos para sincronizar a execução de várias instâncias.

e

O enterprise bean não deve tentar gerenciar encadeamentos. O enterprise bean não deve tentar iniciar, parar, suspender ou retomar um encadeamento ou alterar a prioridade ou o nome de um encadeamento. O enterprise bean não deve tentar gerenciar grupos de encadeamentos.

O motivo é que os EJBs devem operar em um ambiente distribuído. Um EJB pode ser movido de uma máquina em um cluster para outra. Threads (e soquetes e outras instalações restritas) são uma barreira significativa a essa portabilidade.


3
Os Java EE7 Concurrency Utils fornecem uma maneira correta de criar threads em um ambiente corporativo. Exemplos aqui e aqui
Chris Ritchie

1
@ Dan Você pode me explicar por que um Thread seria uma barreira significativa à portabilidade de mover um EJB de uma máquina em um cluster para outro?
Geek

13

O motivo pelo qual você não deve gerar seus próprios threads é que eles não serão gerenciados pelo contêiner. O contêiner cuida de muitas coisas que um desenvolvedor iniciante pode achar difícil de imaginar. Por exemplo, coisas como pool de threads, clustering, recuperações de falhas são executadas pelo contêiner. Ao iniciar um tópico, você pode perder alguns deles. Além disso, o contêiner permite reiniciar seu aplicativo sem afetar a JVM na qual ele é executado. Como isso seria possível se houver threads fora do controle do contêiner?

Esse é o motivo pelo qual os serviços de timer J2EE 1.4 foram introduzidos. Veja este artigo para detalhes.


2
O JSR 236 adicionou recursos para suportar encadeamentos de geração no Java EE 7 e posterior. Veja este irmão Resposta de Chris Ritchie .
Basil Bourque 24/05

8

Utilitários de simultaneidade para Java EE

Agora existe uma maneira padrão e correta de criar encadeamentos com a API Java EE principal:

Ao usar o Concurrency Utils, você garante que seu novo encadeamento seja criado e gerenciado pelo contêiner, garantindo que todos os serviços de EE estejam disponíveis.

Exemplos aqui


2

Você sempre pode dizer ao contêiner para iniciar as coisas como parte de seus descritores de implantação. Eles podem fazer as tarefas de manutenção necessárias.

Siga as regras. Você ficará feliz em algum dia que você fez :)


2

Os encadeamentos são proibidos nos contêineres Java EE de acordo com os blueprints. Por favor, consulte os projetos para mais informações.


2

Não há motivo real para não fazê-lo. Eu usei o Quarz com o Spring em um aplicativo da web sem problemas. Também a estrutura de simultaneidade java.util.concurrentpode ser usada. Se você implementar seu próprio manuseio de encadeamento, configure os theads para deamon ou use um próprio grupo de encadeamentos de deamon para eles, para que o contêiner possa descarregar seu aplicativo da Web a qualquer momento.

Mas tenha cuidado, a sessão e a solicitação do escopo do bean não funcionam em threads gerados! Além disso, outro código bloqueado ThreadLocalnão funciona imediatamente , você precisa transferir os valores para os segmentos gerados por si mesmo.


1

Eu nunca li que isso é desencorajado, exceto pelo fato de que não é fácil fazer corretamente.

É uma programação de baixo nível e, como outras técnicas de baixo nível, você deve ter um bom motivo. A maioria dos problemas de simultaneidade pode ser resolvida com muito mais eficiência usando construções internas, como conjuntos de encadeamentos.


7
é de fato proibido pelas especificações.
Ken Liu

1

Um motivo que eu encontrei se você gerar alguns encadeamentos no EJB e tentar fazer com que o contêiner descarregue ou atualize o EJB, você terá problemas. Quase sempre há outra maneira de fazer algo em que você não precisa de um Thread; basta dizer NÃO.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.