2012-01-25 49 views
2

我很困惑,如果我們應該在servlet中創建自己的線程,因爲它們在內部具有線程機制 ?.如果是,我們如何確保程序線程安全?如何在servlet中實現線程安全機制。在servlets中使用線程

+1

儘管它沒有明確的非法,我會盡量避免在servlet中創建線程。結果可能無法預測,或取決於您使用的容器。你能否更詳細地解釋你的需求以及爲什麼你需要創建自己的線程?一般來說,你的代碼需要是線程安全的,因爲容器可能會從不同的線程調用同一個servlet對象。在servlet規範中有很多這方面的信息。 –

+0

事情是我正在閱讀日誌文件,然後根據嚴重程度發送郵件。這個過程正在不斷髮生,但我注意到有時它缺少郵件。因此,我想爲郵件部分使用不同的線程,以及如果我必須在山姆時間讀取多個文件。如何在不使用線程的情況下實現這一目標? – Rookie

回答

1

從你在評論中寫的內容可以看出,如果在日誌中發現了某種間歇性事件,你就有一組線程持續監視日誌文件併發送電子郵件。

第一個問題:爲什麼這是一個servlet?有沒有web-gui?這用於什麼?

對於日誌掃描部分,我會將它作爲一個單獨的進程實現在servlet容器之外。對於需要發送到某個地方的所有過程,我會將消息添加到JMS隊列中。然後,我將創建一個消息驅動bean來接收來自該隊列的消息並將它們作爲電子郵件發送。(這實際上是一個集成問題,將消息從JMS轉換爲電子郵件,您可能希望查看類似Mule的內容來解決此問題)。

至於如何將它與你的servlet整合,這取決於你的servlet確實除了掃描日誌(我想它提出了某種界面的用戶)

採用這種設計的東西,你可以選擇重新編寫將來生成日誌的程序。第一個程序不是隻有一個程序寫入日誌和另一個程序解析日誌,而是直接在JMS隊列上放置中間消息。換句話說,您可以在將來更改您的架構的日誌生成部分,而無需重新編寫郵件發送部分。

+0

是的你是對的。我正在使用定時器掃描日誌文件,並在發生問題時發送郵件。 現在的問題,爲什麼這是一個servlet,所以當我想知道它運行良好時,我可以得到響應。 現在的事情是當我發送郵件使用新線程它給內存泄漏的問題,因爲它是無法停止線程時,我停止應用程序或server.so你說我應該使用JMS隊列,這是正確的? – Rookie

+1

如果您讓實施日誌掃描,則您的日誌掃描線程不會干擾應用程序服務器線程。在實現與JMS的通信時,應用程序服務器會爲您處理線程,並僅在存在實際消息時才調用您的消息處理代碼。爲了監視外部日誌掃描過程,它可以定期發送「我還活着」的消息,並且該小服務程序可以報告何時發生最後一個「我還活着」(並且它可能會明顯地報告其他事情,例如收到的消息數量和發送的郵件數量) –

1

我也有類似的關注。

只有EJB規範禁止從應用程序創建線程。

可以從servlet啓動線程。
我已經沒有任何問題,但做了很多次,說實話我不是100%肯定:

  • 這是由容器允許的,但違反標準

  • 它被所有容器所允許。

但在Tomcat中,我從來沒有從servlet開始線程的問題。

您可以像在每個多線程程序中一樣使線程安全。

您將使用Java提供的所有可用結構進行同步。

+2

從servlet規範(版本3.0,第1.2章):「例如,高端應用程序服務器可能會限制創建一個Thread對象,以確保容器的其他組件不會受到負面影響。」 –

2

你問兩個不同的問題:

我是否應該讓我們自己的線程在servlet或不糊塗,因爲 他們內部的線程機制?

通常情況下,您不應該在Java EE應用程序中啓動線程。如果您需要單獨的線程,請確保使用應用程序知道的Scheduler Service,以便在應用程序關閉時有機會關閉線程。石英是大部分時間使用的。

如果是的話我們如何確定程序線程是否安全?如何到 在servlets中實現線程安全機制。

Servlets和其他任何Java類一樣。查找關於線程安全的教程或閱讀Java Concurrency in Practice

+0

我正在使用Timer類,當我停止部署我的程序的tomcat服務器時,我無法停止線程 – Rookie

+1

@raghav Timer是一個古老的遺蹟。您應該切換到Java 1.5中引入的ExecutorService接口。 ['Executors.newScheduledThreadPool(poolSize)'](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html#newScheduledThreadPool%28int%29)應該是你需要的 –

+0

這樣,您可以在關閉Web應用程序時調用ExecutorService.shutdown()。 –