1. 程式人生 > >Web應用啟動時,後臺自動啟動一個執行緒(轉)

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結束、使用者請求到達等。

Web應用啟動時,後臺自動啟動一個執行緒

    其中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進行一下配置:

Web應用啟動時,後臺自動啟動一個執行緒
啟動專案,你就會發現你媽媽喊你回家吃飯。。。。

 

(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進行一下配置:

Web應用啟動時,後臺自動啟動一個執行緒
啟動專案,你同樣會發現你媽媽喊你回家吃飯。。。。
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之前。

   下面來看一後臺啟動的列印截圖,你就會發現!

    第一種方式:

Web應用啟動時,後臺自動啟動一個執行緒
     也就是說listener在web應用起來之前已經開始start了
第二種方式:

Web應用啟動時,後臺自動啟動一個執行緒

     servlet必須在web應用完全啟動完畢之後才開始運行了!