天天看點

java定時器使用

定時器類timer在java.util包中。使用時,先執行個體化,然後使用執行個體的schedule(timertask task, long delay)方法,設定指定的任務task在指定的延遲delay後執行。定時器任務類timertask是抽象類,繼承并重寫其run()方法,可實作具體任務。

schedule(timertask task, date time)設定指定任務task在指定時間time執行。

cancel()方法結束這個定時器。

schedule(timertask task, long delay, long period)方法設定指定任務task在指定延遲delay後進行固定延遲peroid的執行。

scheduleatfixedrate(timertask task, long delay, long period)方法設定指定任務task在指定延遲delay後進行固定頻率peroid的執行。

要實作一個定時任務,運用java中的timer和timertask類可以非常容易實作實時調用處理函數。這兩個類使用起來非常友善,可以完成我們對定時器的絕大多數需要。

看個簡單的例子:

import java.io.ioexception;

import java.util.timer;

public class timertest {

public static void main(string[] args){

timer timer = new timer();

timer.schedule(new mytask(), 1000, 2000);//在1秒後執行此任務,每次間隔2秒,如果傳遞一個data參數,就可以在某個固定的時間執行這個任務.

while(true){//這個是用來停止此任務的,否則就一直循環執行此任務了

try {

int ch = system.in.read();

if(ch-'c'==0){

timer.cancel();//使用這個方法退出任務

}

} catch (ioexception e) {

// todo auto-generated catch block

e.printstacktrace();

static class mytask extends java.util.timertask{

@override

public void run() {

// todo auto-generated method stub

system.out.println("________");

servlet偵聽器結合java定時器實作任務計劃排程[轉]

好多朋友用過windows的任務計劃,也有不少程式迷自己曾寫過時鐘報警、系統自動關機等趣味程式,可卻很少有朋友在web工程中實作過類似功能。今天有空把筆者先前曾在tomcat上實作的類似功能,搬出來與大家共享。

    早在幾年前,我公司跟某市财政局合作項目開發,為加強财政局對所屬機關财務狀況的有效監管,開發、實施了财政局資料中心項目。此項目采用b/s加c/s混合結構模式。财政局web伺服器上架設資料同步接收裝置,由市屬機關每天下班前把财務資訊通過http協定上傳至财政局中心伺服器,與web伺服器上的接收裝置對接。财政局内部各部門需要查閱大量财務資訊,擷取完備的市屬機關目前财務狀況資訊,各部門按職能劃分,需要準确的擷取各部門各自所關注的彙總資訊,以财政報表的形式提供。

    因财政資料量大,實時計算财政報表速度較慢,當初就考慮用報表緩存來減輕伺服器的負擔,但用緩存需要一個合理的緩存更新機制。考慮到各市屬機關每天下班前才把财務資料上傳,财政局每天所檢視到的财務資訊其實并不包括當天(除非有某位上司等到所屬機關全部上傳完之後才來檢視資訊,應該已經下班了),是以要是能實作任務計劃排程,在每晚深夜把當天及曆史财務資訊彙總,更新緩存,速度瓶頸不就解決了嗎。

    當時由于系統核心是基于web部署的,報表計算引擎也相應的部署在tomcat容器上,是以如果想要借用windows的任務計劃來實作定時計算,就需要額外編寫普通桌面應用程式接口,稍顯複雜。于是就琢磨着想在web上實作,經過查閱較多相關資料,發現java定時器(java.util.timer)有定時觸發計劃任務的功能,通過配置定時器的間隔時間,在某一間隔時間段之後會自動有規律的調用預先所安排的計劃任務(java.util.timertask)。另外,由于我們希望當web工程啟動時,定時器能自動開始計時,在整個web工程的生命期裡,定時器能在每晚深夜觸發一次報表計算引擎。是以定時器的存放位置也值得考查,不能簡單的存在于單個servlet或javabean中,必須能讓定時器宿主的存活期為整個web工程生命期,在工程啟動時能自動加載運作。結合這兩點,跟servlet上下文有關的偵聽器就最合适不過了,通過在工程的配置檔案中加以合理配置,會在工程啟動時自動運作,并在整個工程生命期中處于監聽狀态。

    下面就servlet偵聽器結合java定時器來講述整個實作過程。要運用servlet偵聽器需要實作javax.servlet.servletcontextlistener接口,同時實作它的contextinitialized(servletcontextevent event)和contextdestroyed(servletcontextevent event)兩個接口函數。考慮定時器有個建立和銷毀的過程,看了前面兩個接口函數,就不容置疑的把建立的過程置入contextinitialized,把銷毀的過程置入contextdestroyed了。

    我把servletcontextlistener的實作類取名為contextlistener,在其内添加一個定時器,示例代碼如下所示(為考慮篇幅,僅提供部分代碼供讀者參考):

    private java.util.timer timer = null;

    public void contextinitialized(servletcontextevent event) {

        timer = new java.util.timer(true);

        event.getservletcontext().log("定時器已啟動");        

         timer.schedule(new mytask(event.getservletcontext()), 0, 60*60*1000);

        event.getservletcontext().log("已經添加任務排程表");

    }

    public void contextdestroyed(servletcontextevent event) {

        timer.cancel();

        event.getservletcontext().log("定時器銷毀");

    以上代碼中, timer.schedule(new mytask(event.getservletcontext()), 0, 60*60*1000)這一行為定時器排程語句,其中mytask是自定義需要被排程的執行任務(在我的财政資料中心項目中就是報表計算引擎入口),從java.util.timertask繼承,下面會重點講述,第三個參數表示每小時(即60*60*1000毫秒)被觸發一次,中間參數0表示無延遲。其它代碼相當簡單,不再詳細說明。

   下面介紹mytask的實作,上面的代碼中看到了在構造mytask時,傳入了javax.servlet.servletcontext類型參數,是為記錄servlet日志友善而傳入,是以需要重載mytask的構造函數(其父類java.util.timertask原構造函數是沒有參數的)。在timer.schedule()的排程中,設定了每小時排程一次,是以如果想實作排程任務每24小時被執行一次,還需要判斷一下時鐘點,以常量c_schedule_hour表示(晚上12點,也即0點)。同時為防止24小時執行下來,任務還未執行完(當然,一般任務是沒有這麼長的),避免第二次又被排程以引起執行沖突,設定了目前是否正在執行的狀态标志isrunning。示例代碼如下所示:

    private static final int c_schedule_hour   = 0;

    private static boolean isrunning = false;

         private servletcontext context = null;

    public mytask(servletcontext context) {

        this.context = context;

    public void run() {

        calendar cal = calendar.getinstance();        

        if (!isrunning)  {           

            if (c_schedule_hour == cal.get(calendar.hour_of_day)) {            

                    isrunning = true;                

                context.log("開始執行指定任務");

                //todo 添加自定義的詳細任務,以下隻是示例

                int i = 0;

                while (i++ < 10) {

                    context.log("已完成任務的" + i + "/" + 10);

                }

                isrunning = false;

                context.log("指定任務執行結束");               

            }            

        } else {

            context.log("上一次任務執行還未結束");

        }

    上面代碼中“//todo……”之下四行是真正被排程執行的示範代碼(在我的财政資料中心項目中就是報表計算過程),您可以換成自己希望執行的語句。

到這兒,servletcontextlistener和mytask的代碼都已完整了。最後一步就是把servletcontextlistener部署到您的web工程中去,在您工程的web.xml配置檔案中加入如下三行:

         com.test.contextlistener

    當然,上面的com.test得換成您自己的包名了。儲存web.xml檔案後,把工程打包部署到tomcat中即可。任務會在每晚12點至淩晨1點之間被執行,上面的代碼會在tomcat的日志檔案中記錄如下:

2003-12-05 0:21:39 開始執行指定任務

2003-12-05 0:21:39 已完成任務的1/10

    ……

2003-12-05 0:21:39 已完成任務的10/10

2003-12-05 0:21:39 指定任務執行結束