定时任务调度工作(学习记录 四)schedule与scheduleAtFixedRate的区别

根据两种情况来看区别

一.首次计划执行的时间早于当前的时间

1.schedule方法

  “fixed-delay”:如果第一次执行时间被延迟了,随后的执行时间按照上一次实际执行完成的时间点进行计算

演示:

public class DifferenceTest {
    public static void main(String[] args) {
        //规定时间格式
        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秒前的时间,若当前时间为2019-04-22 15:44:50
        //那么设置之后的时间变成2019-04-22 15:44:44
        calendar.add(Calendar.SECOND, -6);
        Timer timer = new Timer();
        //第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is:" +
                sf.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(),2000);

    }
}

执行效果:

2.scheduleAtFixedRate方法

  “fixed-rate”;如果第一次执行时间被延迟了,随后的执行时间按照上一次开始的时间点进行计算,

并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步。

演示:

public class DifferenceTest {
    public static void main(String[] args) {
        //规定时间格式
        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秒前的时间,若当前时间为2019-04-22 15:44:50
        //那么设置之后的时间变成2019-04-22 15:44:44
        calendar.add(Calendar.SECOND, -6);
        Timer timer = new Timer();
        //第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is:" +
                sf.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(),2000);

    }
}

执行效果如下:

如图,因为设置了每隔2s执行一次,第一次执行时间比当前时间提早了6s,所以它会从原定最早的时间,先直接执行三次,来追上现在的进度。


二.任务执行时间超出执行周期间隔

1.schedule方法

  下一次执行时间相对于上一次实际执行完成的时间点,因此执行时间会不断延后。

演示:

public class DifferenceTest {
    public static void main(String[] args) {
        //规定时间格式
        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 = new Timer();
        //第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is:" +
                sf.format(scheduledExecutionTime()));
                System.out.println("Task executes!");
            }
        }, calendar.getTime(),2000);
    }
}

执行结果:

用sleep,模拟执行任务时间为三秒,大于任务间隔时间。

2.scheduleAtFixedRate方法

  下一次执行时间相对于上一次开始的时间点,因此执行时间一般不会延后,因此存在并发性。

演示:

public class DifferenceTest {
    public static void main(String[] args) {
        //规定时间格式
        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 = new Timer();
        //第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is:" +
                sf.format(scheduledExecutionTime()));
                System.out.println("Task executes!");
            }
        }, calendar.getTime(),2000);
    }
}

执行结果如下:

不会被任务执行所需要时间影响。

原文地址:https://www.cnblogs.com/xk920/p/10751505.html

时间: 2024-08-30 06:27:05

定时任务调度工作(学习记录 四)schedule与scheduleAtFixedRate的区别的相关文章

高可用mongodb集群的学习记录(四mongodb分片集群搭建)

无论oracle还是mysql数据库都有分区的概念,即同一张表物理上不在同一台机器上,有效缓解了表都集中存在一台机器的压力.当然,mongodb也有类似的机制,即是分片.具体理论知识大家可以参考网上文档,我这里只记录下具体操作步骤 参考网络上一个图.我选用的是2个副本集+1个仲裁.实际上我这里分片集群需要3个mongos,3个config server,数据分片3个shard server,对应着还有3个副本,3个仲裁节点,总共需要15个实例.因为我资源确实紧张,又不想影响实验效果.冥思苦想了一

schedule() 和 scheduleAtFixedRate() 的区别--转载

1.  schedule() ,2个参数方法:在执行任务时,如果指定的计划执行时间scheduledExecutionTime <= systemCurrentTime,则task会被立即执行. 2.  schedule() ,3个参数方法:在执行任务时,如果指定的计划执行时间scheduledExecutionTime <= systemCurrentTime,则task会被立即执行,之后按period参数固定重复执行. 3.  scheduleAtFixedRate() ,3个参数方法:在

定时任务调度工作(学习记录 一)

Timer是jdk自带的,不用引入其他jar包,而Quartz需要引入 前者简单,功能简洁,后者复杂,功能繁多. 实际应用中,只用关注Timer与TimerTask 创建两个类: 首先是MyTimerTask,它需要继承TimerTask,这个是java.util下的 public class MyTimerTask extends TimerTask{ private String name; public MyTimerTask(String inputName) { name = inpu

Mybatis学习记录(四)--高级查询和缓存

这些都是连贯的学习笔记,所以有的地方因为之前都说过,所以也就没怎么写详细了,看不太明白的可以看看之前的笔记. 一.高级查询 高级查询主要是一对一查询,一对多查询,多对多查询 1.一对一查询 有用户和订单两个表,用户对订单是1对1查询.也就是订单中有一个外键是指向用户的. 先创建实体类: User.java public class User { private int id; private String username; private String password; private St

产品需求文档的学习记录(四)

前三篇文章我们逐步梳理了产品的信息结构.框架结构.界面结构(原型),这一步我们就要根据之前完成的工作,开始正式撰写产品需求文档了(PRD文档). 通过之前的准备工作,我们更加清楚了产品的需求,并细致的考虑了方案的可行性,从而减少与避免了撰写文档时容易忽略的细节黑洞. PRD文档没有标准的规范,也没有统一的模板,每个公司都不一样,并且每个人也不一样,这个取决于个人习惯和团队要求.虽然PRD文档没有标准的规范,但是有两项是必不可少的,那就是文件标识和修改记录.文档在撰写过程中,我们可以自行不断的修改

Maven学习记录(四)--多模块开发配置

多模块的好处就是协同开发,对于大的项目这样分工可以提高效率,同时减轻代码耦合,看起来也一目了然,maven多模块还解决了不同人开发使用的架包版本冲突等问题 一.创建项目 1.创建父级容器 不要使用模板,直接创建,创建后就可以直接把src目录删除,这个容器是用来承载其他子项目的 2.创建子项目 直接对着父项目右键,然后创建module,选择你需要用到的模板 3.创建后IDEA生成的配置 首先是目录结构, 对应的maven结构,root代表父项目 父项目的pom.xml,IDEA很智能的把要配置的都

SpringMVC学习记录(四)--文件上传

学习一个框架少不了学习文件上传 在使用springMVC进行系统实现时,springMVC默认的解析器里面是没有加入对文件上传的解析的,这可以方便我们实现自己的文件上传.但如果你想使用springMVC对文件上传的解析器来处理文件上传的时候就需要在spring的applicationContext里面加上springMVC提供的MultipartResolver的申明.这样之后,客户端每次进行请求的时候,springMVC都会检查request里面是否包含多媒体信息,如果包含了就会使用Multi

Tornado学习记录四

Structure of a Tornado web application A Tornado web application generally consists of one or more RequestHandler subclasses, an Application object which routes incoming requests to handlers, and a main() function to start the server. tornado 应用通常包括至

Spring学习记录(四)---bean之间的关系:继承、依赖

     继承 这里说的继承和java的继承是不一样的,不是父类子类.但思想很相似,是父bean和子bean 1.父bean是一个实例时.它本身是一个完整的bean 2.父bean是模板,抽象bean,不能被实例化,只是来被继承. 当遇到一个类要实例化出很多相似的bean对象时,如下,看起来是不是很不简洁 1 <bean id="address1" class="com.guigu.spring.autowire.Address" 2 p:city="