2014-09-29 103 views
0

在閱讀了很多不同的東西並且完全不熟悉這些東西中的正確術語之後,我想知道在創建線程時正確的方式是什麼tomcat啓動特定用途。我正在使用一個linux系統。在啓動時在tomcat中創建任務線程的正確方法

我不想從一個servlet創建一個線程,並且我對這個不好的原因有個好主意。當tomcat啓動時,我想要兩個不同的線程有獨特的目的開始。第一個線程每隔30分鐘運行一次,以審計後端數據。第二個線程負責發送電子郵件。當請求運行一個必須發送電子郵件的servlet時,我不想阻止等待發送電子郵件的servlet,而是要發送一個請求到這個電子郵件線程並繼續前進。所以一個定期運行,一個按需運行。我從來不需要增加執行這些任務的線程數,我只需要這兩個就可以了,只要webapp正在運行,並且如果webapp必須停止,我就不會在意曼妙關掉。

有我知道我可以採取一些辦法:

  1. 以外的tomcat創建運行的過程和定義的方式與我的servlet這一進程進行通信。如果可能的話,我想避免這種情況,因爲我希望這兩個線程首先直接與啓動和關閉Web應用程序相關聯,並且他們能夠訪問ServletContext中的數據,而不是必須通過通信通道傳送/接收數據。

  2. 在我的一個servlet的init方法中產生兩個線程。這看起來很骯髒和黑客,但它肯定會完成工作。

  3. 創建一個ServletContextListener,它擴展了ThreadPoolExecutor或其他ExexutorService。這似乎有吸引力和正確的,我想我可以做一個固定的2線程線程池,因爲我不需要更多。但是,這是推薦的方式來做我想要的嗎?據我所知,ExecutorService實際上更適用於執行Runnable,而不必失去創建線程的開銷。我不知道這是否完全正確,但如果是這樣,我不會爲了其目的而使用執行者。

也許有更多的方法,我不知道或實現上述之一的正確方法。

+2

首先,**這與Tomcat **無關,請編輯該問題。你的問題是你如何在_web application_中啓動服務線程。其次,你的第三種方法幾乎是正確的 - 但不要「擴展」,這當然是錯誤的。另外,考慮兩個聽衆,因爲這些聽衆似乎是各自關心的問題,將他們分組在一起也是一種駭客。確保你理解並使用'ScheduledExecutorService'並確保你正確關閉你的執行程序。 – 2014-09-29 13:45:14

+0

聽起來像你真正想要的是兩個[Singleton](http://stackoverflow.com/q/70689/823393)s。 – OldCurmudgeon 2014-09-29 14:08:24

+0

關於這個與tomcat無關的問題,我特別提到了tomcat,因爲我會嘗試在WebSphere中使用'WorkManager'來做這樣的事情,並且我會將'Work'傳遞給它。我不相信Tomcat本身具有這種能力(儘管我認爲JBOSS可能),所以我特別對像Tomcat這樣的輕量級servlet處理器的選擇感興趣。 – 2014-09-29 18:29:05

回答

1

請參考以下Q & A:tomcat 6 thread pool for asynchronous processing

此外,您可能需要Executors.newScheduledThreadPool來創建ScheduledExecutorService的實例,該實例能夠執行重複任務。

希望這有助於...

+0

爲單一按需線程使用'Executors.newFixedThreadPool'和爲我的定期任務使用'Executors.newScheduledThreadPool'是否有意義?僅僅選擇一個線程會更有意義,例如,兩個線程都使用'fixedThreadPool',並將我的週期性任務調整到這個線程上? (正如在使用'Thread.sleep(30分鐘)''以確保週期?) – 2014-09-29 17:49:42

+1

@MichaelPlautz不要使用相同的池的兩個任務,因爲這兩個任務是完全無關的(從你描述他們的方式)。而且從來沒有**使用Thread.sleep - 如果你正在考慮使用它,那麼你正在做的事情非常錯誤。 – 2014-09-30 07:42:20

+0

@MichaelPlautz我完全同意'Boris the Spider' - **從來沒有**使用Thread.sleep **或類似的方法,因爲它是**在Java中使用多線程的低級方式,應該是僅**使用**如果需要使用** ExecutorService **和/或** ScheduledExecutorService **無法實現的非常特定的多線程邏輯,它們被視爲**高級**(因此**更少的錯誤傾向**)在Java中使用多線程的方式。 – Yura 2014-09-30 08:58:33

1

我不會去執行線程池本身,而是取決於你的問題:

正確的方式在啓動

建立在Tomcat的任務線程的人說,你的第三個方法幾乎是正確的但是這取決於您的服務結構。

我給你舉個例子,然後解釋:

public class YourServletContextListener implements ServletContextListener{  
    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 

    }   
    @Override 
    public void contextInitialized(ServletContextEvent sce) { 

    } 
} 

從文檔:

contextInitialized: 

所有的ServletContextListener通知上下文初始化的 任何過濾器或servlet之前在web應用程序中初始化爲

如果我正確理解你的方法,那麼我會問你:你想如何啓動一個服務或發送任何請求到一個尚未初始化的servlet?

如果您想要啓動的服務不直接與Web應用程序進行通信/需要任何servlet或過濾器或任何數據,這將起作用。稍後,在啓動容器後,他們可以確保相互通信。

正如我之前所說,最好使用哪種方式取決於服務結構/邏輯。

一種其他方法可被使用的過濾器:

void init(FilterConfig filterConfig) throws ServletException 

由web容器調用以指示它正在 投入使用的過濾器。在實例化過濾器後,servlet容器僅調用一次init方法 。

void destroy() 

由web容器調用以指示它正在 退出服務的過濾器。只有在過濾器的doFilter方法中的所有線程 已退出或超過 時間段過去後才調用此方法。在Web容器調用此方法後,它將在此過濾器實例上不會再次調用doFilter方法 。

此方法使過濾器清理的任何資源 正在舉行的(例如,內存,文件句柄,線程)和 確保任何持久性狀態與內存中的過濾器的 當前狀態同步的機會。

但過濾器不是爲這種方法而設計的!

,如果你想攔截的MACHING一個 特定的URL模式,因爲要檢查/修改HTTP 請求/響應HTTP請求使用過濾器。如果您希望 在webapp的啓動和/或關閉時截獲,請使用ServletContextListener。

相關問題