2012-10-31 18 views
2

我在Adam Bien的JavaEE黑客入門書中讀到,雖然在EJB容器上禁止創建線程,但Web容器並非如此。他實際上在他的Tomcat上運行的X射線探針中創建了一個線程池執行程序。JavaEE中的線程創建EJB/Web容器

我現在有點困惑。雖然我遇到了必須在EE應用程序中執行手動線程池管理的情況,但我可以理解爲什麼在JavaEE容器中手動創建線程是一個壞主意。但是,當您可以將大部分EJB部署到任一個EJB容器時,我不明白EJB容器和關於線程創建的Web容器之間的區別。如果會話bean在Web容器中產生線程沒有任何問題,那麼將相同的會話Bean部署到EJB容器可能會導致什麼問題?

回答

10

這就是Java EE的「企業」部分滿足現實世界的地方。

使用「企業」系統的前提大多是以管理爲中心。特別將決策和配置放在容器上,而不是依靠應用程序本身來管理這些資源。通過將資源的創建和管理與應用程序代碼分離開來並依賴於容器,系統管理員可以看到並訪問這些資源,從而有可能以更高的級別和通用的方式調整和監視應用程序,而不是使用特定於應用程序的機制。因此,這就是我們所處的環境,這是推動Java EE規範的這些「規則」關於你能做什麼以及不能做什麼(不應該)的原因的一部分。

現在,servlet容器規範,更加狂野西部。它沒有所有這些「企業」管理功能(介意,許多容器暴露他們,但規範沒有提及它們)。例如,提供靜態文件是Web容器的麪包和黃油功能,因此限制開發人員訪問所述文件幾乎沒有意義。此外,servlet規範在EJB規範之前出現,並且被錨定到環境中,而不是根據該環境重做。

這給你兩個「矛盾」的規範就特定的東西(如線程)而言。

所以,是的,儘管那些線程池可能在完全相同的JVM中(並且因此「不可控制地」使用了Java EE,但即使在Java EE應用程序中,Servlet規範也允許「管理」自己的線程池資源)作爲Java EE容器。

這在現實世界中意味着什麼,是的,如果你願意,你可以在Java EE容器或servlet容器中隱藏線程等。流行的容器都沒有禁止你這樣做(WebSphere可能,我不使用它)。

但是,你不應該。 Java EE(特別是Java EE 6)具有機制和箍環,您可以跳過這些機制並使用它來代替使用線程池。諸如WorkManagers,JMS隊列,異步會話bean,計時器作業等。

在一個servlet應用程序中,大多數這些機制都不存在,所以您不能利用它們,因此您只需使用「僅Java」。

在使用Java EE應用程序部署的Web應用程序中使用「Just Java」的後果是容器中的可見性。例如,您的Web應用程序將需要自己的配置變量來設置其線程池的大小,並且不能依賴容器來管理它。

最後,這通常是沒有什麼大不了的。 Java EE的大部分複雜性都以許多人不使用的管理功能爲中心。對於我自己,我使用Java EE,很少使用普通的WAR,我喜歡儘可能多地將內容插入容器 - 讓它工作。也就是說,我在Java EE容器中的WAR中運行自定義套接字服務器,打破了每個可以想象的規則,因爲這樣做容易得多。 「Java EE方式」並不是我們想要做的足夠靈活的地方,所以我們選擇了「Just Java」並將代碼注入戰爭中,以便我們可以在Wild Wild West中玩,男人是男人,管理自己的線程。

+0

謝謝您的全面回答。我在Java EE方面沒有太多的專業知識,但我認爲,儘管平臺具有全面性,但我並不認爲寬鬆總是違反這些規則的原因。 –

2

EJB是由服務器管理的。管理意味着依賴注入。如果您使用註釋從類生成線程,服務器將無法處理它們(執行@PostConstruct,注入引用等)。

+0

它是唯一的問題嗎?如果我想在不需要容器管理設施的情況下進行多線程計算或網絡操作,那麼手動創建線程池是否是一種很好的做法? –

+0

線程池由服務器/容器管理,它應該保持這種狀態。你確定你的計算不能由有狀態/無狀態bean完成嗎?因爲這是Enterprise Java Beans的哲學 - 忘記線程,使用bean。 但是,它並不像你不能在EJB容器中創建線程...... –

+0

另外,就我所記得的(找不到任何確切的引用)而言,EJB容器儘可能多地佔用內存(並管理它),因此創建線程那些對內存要求較高的內存可能會導致「內存不足」異常,因爲容器不會釋放它,就像它與其管理的其他對象一樣。 –

0

EJB始終在EJB容器中執行,所以不應該在EJB中手動創建線程。即使它們是作爲WAR文件(Web模塊)的包,它們也會在EJB容器中執行,並且在創建線程方面具有相同的限制。

但是,servlet和過濾器在Web容器中執行,沒有任何東西禁止他們擁有自己的手動管理線程池。