Java多執行緒——守護執行緒

gary-liu發表於2017-02-16

執行緒分類

在Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒)

作用

Daemon的作用是為其他執行緒的執行提供便利服務,守護執行緒最典型的應用就是 GC (垃圾回收器),它就是一個很稱職的守護者。

區別

User和Daemon兩者幾乎沒有區別,唯一的不同之處就在於虛擬機器的離開:如果 User Thread已經全部退出執行了,只剩下Daemon Thread存在了,虛擬機器也就退出了。 因為沒有了被守護者,Daemon也就沒有工作可做了,也就沒有繼續執行程式的必要了。

不要用守護執行緒去做事情,因為主執行緒很快就執行完了,虛擬機器退出,Daemon停止服務,輸出操作自然失敗了。

優先順序:守護執行緒的優先順序比較低,用於為系統中的其它物件和執行緒提供服務。

當JVM中所有的執行緒都是守護執行緒的時候,JVM就可以退出了;如果還有一個或以上的非守護執行緒則JVM不會退出。

應用

在使用長連線的comet服務端推送技術中,訊息推送執行緒設定為守護執行緒,服務於ChatServlet的servlet使用者執行緒,在servlet的init啟動訊息執行緒,servlet一旦初始化後,一直存在伺服器,servlet摧毀後,訊息執行緒自動退出。Servlet容器預設採用單例項多執行緒的方式來處理請求,這樣減少產生Servlet例項的開銷。

為什麼要用守護執行緒?

我們知道靜態變數是ClassLoader級別的,如果Web應用程式停止,這些靜態變數也會從JVM中清除。但是執行緒則是JVM級別的,如果你在Web 應用中啟動一個執行緒,這個執行緒的生命週期並不會和Web應用程式保持同步。也就是說,即使你停止了Web應用,這個執行緒依舊是活躍的。正是因為這個很隱晦 的問題,所以很多有經驗的開發者不太贊成在Web應用中私自啟動執行緒。
如果我們手工使用JDK Timer(Quartz的Scheduler),在Web容器啟動時啟動Timer,當Web容器關閉時,除非你手工關閉這個Timer,否則Timer中的任務還會繼續執行!

Spring為 JDK Timer 和 Quartz Scheduler 所提供的TimerFactoryBean 和 SchedulerFactoryBean能夠和Spring容器的生命週期關聯,在 Spring容器啟動時啟動排程器,而在Spring容器關閉時,停止排程器。所以在Spring中通過這兩個FactoryBean配置排程器,再從 Spring IoC 中獲取排程器引用進行任務排程將不會出現這種Web容器關閉而任務依然執行的問題。而如果你在程式中直接使用Timer或Scheduler,如不進行額外的處理,將會出現這一問題。

[參考資料]

Java中守護執行緒的總結

相關文章