Java定時器之Timer學習二

Wayfreem發表於2019-01-19

方法名稱 schedule() 和 scheduleAtFixedRate() 的區別

兩種情況看區別

  • 首次計劃執行的時間早於當前時間

比如說:當前時間是 11:06, 但是首次計劃執行的時間應該為: 11:00

  • 任務執行所需的時間超出任務的執行週期間隔

比如說:我們執行的任務的時間為 3秒,但是任務執行的週期間隔為 2秒

詳細分析

首次計劃的時間早於當前時間

schedule 方法

fixed-delay; 如果第一次執行的時間被 delay 了,隨後的執行時間按照上一次實際執行完成的時間點進行計算。

程式碼例項

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {
    
    public static void main(String[] args) {
        
        // 獲取當前時間按照指定的格式輸出
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        System.out.println("current time is:"+ sf.format(calendar.getTime()));
        
        // 設定成6秒之前的時間
        calendar.add(Calendar.SECOND, -6);
        System.out.println("current time minus six second is :"+ sf.format(calendar.getTime()));
        System.out.println("Task is being executed!");
        
        // 使用 timer 來執行
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("scheduled exec time is :"+ sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
         
    }

}

控制檯輸出

current time is:2018-07-05 13:09:57
current time minus six second is :2018-07-05 13:09:51
scheduled exec time is :2018-07-05 13:09:57
scheduled exec time is :2018-07-05 13:09:59
scheduled exec time is :2018-07-05 13:10:01
scheduled exec time is :2018-07-05 13:10:03
scheduled exec time is :2018-07-05 13:10:05
scheduled exec time is :2018-07-05 13:10:07
scheduled exec time is :2018-07-05 13:10:09

schedule 方法總結

雖然我們是將事件提前了6秒,但是使用 schedule 還是從當前時間開始執行。然後每隔兩秒執行一次。

scheduleAtFixedRate 方法

fixed-rate; 如果第一次執行時間被 delay了,隨後的執行時間按照上一次開始的點計算,並且為了趕上進度會多次執行任務,因為 TimerTask中的執行需要考慮同步

程式碼例項

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {
    
    public static void main(String[] args) {
        
        // 獲取當前時間按照指定的格式輸出
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        System.out.println("current time is:"+ sf.format(calendar.getTime()));
        
        // 設定成6秒之前的時間
        calendar.add(Calendar.SECOND, -6);
        System.out.println("current time minus six second is :"+ sf.format(calendar.getTime()));
        
        // 使用 timer 來執行
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("scheduled exec time is :"+ sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
         
    }

}

控制檯輸出

current time is:2018-07-06 14:32:34
current time minus six second is :2018-07-06 14:32:28
scheduled exec time is :2018-07-06 14:32:28
scheduled exec time is :2018-07-06 14:32:30
scheduled exec time is :2018-07-06 14:32:32
scheduled exec time is :2018-07-06 14:32:34
scheduled exec time is :2018-07-06 14:32:36
scheduled exec time is :2018-07-06 14:32:38

scheduleAtFixedRate 方法總結

我們可以看到實際的效果是:在啟動執行的時候,會立馬執行3次,就是為了追趕已經過去的6秒。然後再按照設定的間隔,每兩秒鐘執行一次。

任務執行所需的時間超出任務的執行週期間隔

schedule 方法

下次執行時間相當於上一次實際執行完成的時間點,因為執行的時間會不斷延後。

程式碼例項

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {
    
    public static void main(String[] args) {
        
        // 獲取當前時間按照指定的格式輸出
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        System.out.println("current time is:"+ sf.format(calendar.getTime()));
        
        // 使用 timer 來執行
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                
                // 模擬當前執行的過程需要 3秒
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 列印最近一次執行的時間
                System.out.println("scheduled exec time is :"+ sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
         
    }

}

控制檯輸出

current time is:2018-07-06 14:43:51
scheduled exec time is :2018-07-06 14:43:51
scheduled exec time is :2018-07-06 14:43:54
scheduled exec time is :2018-07-06 14:43:57
scheduled exec time is :2018-07-06 14:44:00
scheduled exec time is :2018-07-06 14:44:03

說明

我們可以空控制檯中輸出的結果中看到:我們當前的時間為 14:43:51,然後第一次計劃執行的時間也為 14:43:51。但是以後每次執行的時間都是相隔 3秒鐘,並不是我們上面設定 timerTask 的時間間隔 2秒。所以說使用 schedule 方法,在這種情況下會不斷的延後。

scheduleAtFixedRate 方法

下一次執行時間相對於上一次開始的時間點,因此執行時間一般不會延後,因此存在併發性

程式碼例項

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class DifferenceTest {
    
    public static void main(String[] args) {
        
        // 獲取當前時間按照指定的格式輸出
        final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        System.out.println("current time is:"+ sf.format(calendar.getTime()));
        
        // 使用 timer 來執行
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                
                // 模擬當前執行的過程需要 3秒
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 列印最近一次執行的時間
                System.out.println("scheduled exec time is :"+ sf.format(scheduledExecutionTime()));
            }
        }, calendar.getTime(), 2000);
         
    }

}

控制檯輸出

current time is:2018-07-07 10:15:51
scheduled exec time is :2018-07-07 10:15:51
scheduled exec time is :2018-07-07 10:15:53
scheduled exec time is :2018-07-07 10:15:55
scheduled exec time is :2018-07-07 10:15:57
scheduled exec time is :2018-07-07 10:15:59

說明

當執行的頻率為2秒鐘,但是執行的時間為3秒的時。我們從控制檯上的輸出可以看到,執行的頻率還是為2秒,因此就會存在併發性。

相關文章