1. 程式人生 > >傳統執行緒技術中的定時器技術

傳統執行緒技術中的定時器技術

傳統執行緒技術中有個定時器,定時器的類是Timer,我們使用定時器的目的就是給它安排任務,讓它在指定的時間完成任務。所以先來看一下Timer類中的方法(主要看常用的TimerTask()方法):

前面兩個是在指定延遲後執行或者重複執行,後面兩個是在指定時間執行或者重複執行。我們以前兩個為例來研究一下定時器的使用。
先寫一個簡單的使用定時器的demo,然後慢慢引申。

public class TraditionalTimer {

    public static void main(String[] args) {
        //簡單定時器的demo
        new Timer().schedule(new TimerTask() {          
            @Override
            public void run() {
                //實際中會扔一個物件進來,我們就可以在這裡操作這個物件的所有方法了
                System.out.println("--boom--");//爆炸
            }
        }, 2000,3000); 

        //列印秒鐘,一秒輸出一次,用來方便觀察的
        while(true) {
            System.out.println(new Date().getSeconds());
            try {
                Thread.sleep(1000);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}

我們用匿名內部類來定義了一個TimerTask物件,需要重寫run()方法,然後執行這個程式,可以看出來第一次2秒鐘後列印“--boom--,後面每隔3秒列印一次。
我們也可以自己來實現上面這個重複執行,我們用定時器的“連環套”!也就是定時器中再套定時器,一個定時器任務執行完了,在任務的最後再裝一個定時器。那麼我們需要先定義一個自己的定時器任務,在自己的定時器任務中再裝一個定時器,把自定義的定時器任務扔進去。然後我們開啟定時器的時候把自己定義的定時器任務扔進去即可。如下:

public class TraditionalTimer {

    public static void main(String[] args) {
        
        //自定義一個定時器任務
        class MyTimerTask extends TimerTask {           
            @Override
            public void run() {
                System.out.println("--boom--");
                //任務執行完再裝一個定時器,扔進自定義的定時器任務
                new Timer().schedule(new MyTimerTask(), 3000);
            }
        }
        new Timer().schedule(new MyTimerTask(), 2000);//外面開啟定時器
        
        while(true) {//列印秒鐘,一秒輸出一次
            System.out.println(new Date().getSeconds());
            try {
                Thread.sleep(1000);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}

這樣的話,我們通過定時器的“連環套”很輕鬆的實現了連環爆炸。但是現在問題來了,上面提供的方法中重複執行都是每隔固定的時間,如果我想要隔2秒執行一次,再隔4秒執行一次,再隔2秒執行一次,再隔4秒執行一次……這該如何實現呢?
可以這樣,我們定義一個全域性的私有成員變數來記錄爆炸次數,奇數的時候隔2秒炸,偶數的次數的話隔4秒炸,或者反過來也行,修改如下:

public class TraditionalTimer {

    private static int count = 0; //記錄爆炸的次數
    public static void main(String[] args) {    

        class MyTimerTask extends TimerTask {           
            @Override
            public void run() {
                count = (count + 1) % 2; //結果只有0和1
                System.out.println("--boom--");
                new Timer().schedule(new MyTimerTask(), 2000+2000*count);//根據count結果設定新的定時時間
            }
        }
        new Timer().schedule(new MyTimerTask(), 2000);
        
        while(true) {//列印秒鐘,一秒輸出一次
            System.out.println(new Date().getSeconds());
            try {
                Thread.sleep(1000);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}

這樣的話,我們就實現了自定義爆炸間隔了。上面這個是通過定義一個全域性私有變數來實現,其實我們也可以這麼幹:不是要實現兩個不同時間間隔的連環炸麼?我可以定義兩個定時器任務A和B,在A執行完開啟定時器,把B任務裝進去,B執行完開啟定時器把A裝進去,這樣也可以。如下:

public class TraditionalTimer {

    public static void main(String[] args) {
        
        new Timer().schedule(new MyTimerTaskA(), 2000);//A和B隨便開一個
        
        while(true) {//列印秒鐘,一秒輸出一次
            System.out.println(new Date().getSeconds());
            try {
                Thread.sleep(1000);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

}
//自定義兩個定時器任務類,繼承TimerTask即可
class MyTimerTaskA extends TimerTask {

    @Override
    public void run() {
        System.out.println("--boomA--");
        new Timer().schedule(new MyTimerTaskB(), 4000);
    }           
}
class MyTimerTaskB extends TimerTask {

    @Override
    public void run() {
        System.out.println("--boomB--");
        new Timer().schedule(new MyTimerTaskA(), 2000);
    }   
}

這樣就可以實現自定義時間間隔的連環炸了。傳統的定時器技術就總結這麼多吧~
更多優質文章和資源,請關注公眾號:【程式設計師私房菜】。