Web應用啟動時,後臺自動啟動一個執行緒(轉)
原文:http://blog.sina.com.cn/s/blog_6810dfc20101ipzq.html
Web應用啟動時,後臺自動啟動一個執行緒
(1)前言
前幾天,manager問道一個問題:能不能實現類似於cron的後臺管理方式。問題解決後,想對這幾個問題進行一下簡單的總結。以便拋磚引玉!首先簡單的提及一下cron。
Cron,計劃任務,是任務在約定的時間執行已經計劃好的工作,這是表面的意思。在Linux中,我們經常用到 cron 伺服器來完成這項工作。cron伺服器可以根據配置檔案約定的時間來執行特定的作務。比如我們可以在配置檔案中約定每天早上4點,對http伺服器重新啟動,這就是一個計劃任務。
在java應用中一種類似的模式就是應用啟動時後臺執行緒的執行,定時的觸發某些任務的執行。目前,這種自啟動的後臺執行緒,有兩種常見的模式:一種是listener,一種是servlet
(2)listener
listener方式是比較常用的。實際上,servelet API 提供了大量監聽器來監聽web應用的內部事件,從而允許當web應用內部事件發生時而回調監聽器的方法,常見的事件有:web應用被啟動、web應用被停止、用session開始、使用者session結束、使用者請求到達等。
其中ServletContextListener用於web應用的啟動和關閉。對於我們剛剛提及的需求,我們需要在web應用啟動的時候就開始啟動後臺的服務執行緒。
ServletContextListener有兩個常用的方法:
void contextInitialized(ServletContextEvent sce)
這個方法在Container初始化整個Web應用時呼叫,執行在該Web應用中servlet和filter初始化之前
void contextDestroyed(ServletContextEvent sce)
這個方法在Container解除安裝整個Web應用時呼叫,執行在該Web應用中servlet和filter的destroy()方法之後
例子:
首先定義一個後臺的服務執行緒
public class run implements Runnable{
@Override
public void run() {
while(true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("you mother call you to go home to eat......")
}
}
}
定義一個listener類
package com.cims;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent e) {
}
public void contextInitialized(ServletContextEvent e) {
System.out.println("------------web start-------");
new Thread(new run()).start();
}
}
最後需要在web.xml進行一下配置:
(3)servlet
無意中,盡然驚訝地發現servlet也有這樣的功能,這得益於load-on-startup 屬性,後面將對該屬性進行一些簡單解析。
服務執行緒仍然保持不變,寫一個servlet(整合HttpServlet)
package com.cims;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class MyServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
public MyServlet(){
}
public void init(){
new Thread(new run()).start();
}
public void doGet(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws ServletException, IOException{
}
public void destory(){
}
}
}
最後需要在web.xml進行一下配置:
啟動專案,你同樣會發現你媽媽喊你回家吃飯。。。。
1.load-on-startup解析
1)load-on-startup元素標記容器是否在啟動的時候就載入這個servlet(例項化並呼叫其init()方法)。
2)它的值必須是一個整數,表示servlet應該被載入的順序
3)當值為0或者大於0時,表示容器在應用啟動時就載入並初始化這個servlet;
4)當值小於0或者沒有指定時,可以由server容器自行決定何時load該servlet。
5)正數的值越小,該servlet的優先順序越高,應用啟動時就越先載入。
6)當值相同時,容器就會自己選擇順序來載入。
2.兩種回家吃飯方式不同
web應用的啟動好比你正在start的一個遊戲,listener好比在你start之前你媽媽就喊你回家吃飯了;servlet方式好比你已經start了,準備打boss時,你媽媽喊你回家吃飯。原因在於ServletContextListener的contextInitialized方法執行在servlet之前。
下面來看一後臺啟動的列印截圖,你就會發現!
第一種方式:
也就是說listener在web應用起來之前已經開始start了
第二種方式:
servlet必須在web應用完全啟動完畢之後才開始運行了!