方法名称 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秒,因此就会存在并发性。


Wayfreem
241 声望33 粉丝

一个后端工程师,偏偏喜欢前端。