理解ScheduledExecutorService中scheduleAtFixedRate和scheduleWithFixedDelay的區別

scheduleAtFixedRate

每間隔一段時間執行,分爲兩種狀況:java

  1. 當前任務執行時間小於間隔時間,每次到點即執行;segmentfault

    /**
     * 任務執行時間(8s)小於間隔時間(10s)
     */
    public class ScheduleTest {
        static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
        public static void main(String[] args) {
            scheduler.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Start: scheduleAtFixedRate:    " + new Date());
                    try {
                        Thread.sleep(8000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("End  : scheduleAtFixedRate:    " + new Date());
                }
            }, 0, 10 , SECONDS);
        }
    }
    
    output:
    
    Start: scheduleAtFixedRate:    Sun Apr 28 14:36:00 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:36:08 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:36:10 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:36:18 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:36:20 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:36:28 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:36:30 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:36:38 CST 2019
    ...
    
    程序啓動時間是14:36:00,之後每間隔10s執行一次(即14:36:十、14:36:20、14:36:30等)。
  2. 當前任務執行時間大於等於間隔時間,任務執行後當即執行下一次任務。至關於連續執行了。ide

    /**
     * 任務執行時間(12s)大於間隔時間(10s)
     */
    public class ScheduleTest {
        static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    
        public static void main(String[] args) {
            scheduler.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Start: scheduleAtFixedRate:    " + new Date());
                    try {
                        Thread.sleep(12000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("End  : scheduleAtFixedRate:    " + new Date());
                }
            }, 0, 10 , SECONDS);
        }
    }
    
    output:
    
    Start: scheduleAtFixedRate:    Sun Apr 28 14:30:13 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:30:25 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:30:25 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:30:37 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:30:37 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:30:49 CST 2019
    Start: scheduleAtFixedRate:    Sun Apr 28 14:30:49 CST 2019
    End  : scheduleAtFixedRate:    Sun Apr 28 14:31:01 CST 2019
    
    程序啓動時間是14:30:13,按理說應該每間隔10s執行一次(即14:30:2三、14:30:33等),但因爲任務執行時間長於10s,下一次的任務要開始的時候發現上次的任務尚未完成,所以阻塞等待,一旦發現上次的任務完成,就立刻啓動。表現出來就是任務延時啓動,最終的效果就是連續執行。

scheduleWithFixedDelay

每當上次任務執行完畢後,間隔一段時間執行。無論當前任務執行時間大於、等於仍是小於間隔時間,執行效果都是同樣的。code

/**
 * 任務執行時間(8s)小於間隔時間(10s)
 */
public class ScheduleTest {
    static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public static void main(String[] args) {
        scheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("Start: scheduleWithFixedDelay: " + new Date());
                try {
                    Thread.sleep(12000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("End  : scheduleWithFixedDelay: " + new Date());
            }
        }, 0, 10 , SECONDS);
    }
}

output:

Start: scheduleWithFixedDelay: Sun Apr 28 14:27:59 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:28:07 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:28:17 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:28:25 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:28:35 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:28:43 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:28:53 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:29:01 CST 2019
...

能夠看出每一個End後,等待了10秒,才啓動下一次Start。
/**
 * 任務執行時間(12s)大於間隔時間(10s)
 */
public class ScheduleTest {
    static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    public static void main(String[] args) {
        scheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                System.out.println("Start: scheduleWithFixedDelay: " + new Date());
                try {
                    Thread.sleep(12000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("End  : scheduleWithFixedDelay: " + new Date());
            }
        }, 0, 10 , SECONDS);
    }
}

output:

Start: scheduleWithFixedDelay: Sun Apr 28 14:26:29 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:26:41 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:26:51 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:27:03 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:27:13 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:27:25 CST 2019
Start: scheduleWithFixedDelay: Sun Apr 28 14:27:35 CST 2019
End  : scheduleWithFixedDelay: Sun Apr 28 14:27:47 CST 2019
...

能夠看出每一個End後,等待了10秒,才啓動下一次Start。

參考

scheduleAtFixedRate vs scheduleWithFixedDelayget

擴展

Spring定時任務@Scheduled註解使用方式淺窺(cron表達式、fixedRate和fixedDelay)it

相關文章
相關標籤/搜索