Java定时任务调度工具详解之Timer篇(初级)

2023-11-05

一.Timer简介

定时任务的基本概念,Timer的函数,综合运用和缺陷


基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务。

Timer 和Quartz

Timer:
出身:由jdk提供,调用方式简单粗暴;
能力:Timer能完成一些简单的定时任务,如需要指定某个具体时间执行任务的话,Timer就能轻松实现。

Quartz
出身:需要引入架包
能力:能完成比较复杂的功能需求
底层机制:能够实现多个执行线程


定义:有且仅有一个后台线程对多个业务线程进行定时定频率的调度

Timer(后台执行线程)对TimerTask(业务线程)的定时调用

这里写图片描述


通过程序来讲解Timer,打开Eclipse

创建java工程MyTimerProject

创建包和class文件

这里写图片描述

这里写图片描述

MyTimerTask.java

package com.vishuo.timer;

import java.util.TimerTask;

public class MyTimerTask extends TimerTask{
    private String name;
    public MyTimerTask(String inputName){
        name=inputName;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        //打印当前name的内容
        System.out.println("Current exec name is:"+name);
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

创建MyTimer类

package com.vishuo.timer;

import java.util.Timer;

public class MyTimer {
  public static void main(String[] args) {
    //1.创建一个timer实例
      Timer timer = new Timer();
    //2.创建一个MyTimerTask实例
      MyTimerTask myTimerTask = new MyTimerTask("No.1");
    //3.通过timer定时定频率调用myTimerTask的业务逻辑
      //即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
      timer.schedule(myTimerTask, 2000L,1000L);
}
}

二.timer定时函数的用法

schedule的四种用法

第一种用法:

schedule(task,time)
参数:task-所要安排的任务
time-执行任务的时间
作用:在时间等于或超过time的时候执行且仅执行一次task

第二种用法

schedule(task,time,period)
参数
task—所要安排的任务
time—首次执行任务的时间
period—执行一次task的时间间隔,单位是毫秒

作用
时间等于或超过time时首次执行task
之后每隔period毫秒重复执行一次task

第三种用法

schedule(task,delay)

参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒

作用:等待delay毫秒后执行且仅执行一次task

第四种用法

schedule(task,delay,period)

参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒
period—执行一次task的时间间隔,单位是毫秒

作用:等待delay毫秒后首次执行task
之后没隔period毫秒重复执行一次task

scheduleAtFixedRate的两种用法

第一种用法:

scheduleAtFixedRate(task,time,period)
参数
task—所要安排的任务
time—首次执行任务前的时间
period—执行一次task的时间间隔,单位是毫秒

作用:时间等于或超过time时首次执行task
之后每隔period毫秒重复执行一次task

scheduleAtFixedRate(task,delay,period)
参数
task—所要安排的任务
delay—执行任务前的延迟时间,单位是毫秒
period—执行一次task的时间间隔,单位是毫秒

作用:等待delay毫秒后首次执行task
之后没隔period毫秒重复执行一次task

全部方法代码示例:

MyTimerTask类

package com.vishuo.timer;

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

public class MyTimerTask extends TimerTask{
    private String name;
    public MyTimerTask(String inputName){
        name=inputName;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        //以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
        //如2016-11-11 00:00:00
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Curren exec time is:"+sf.format(calendar.getTime()));
        //打印当前name的内容
        System.out.println("Current exec name is:"+name);
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

MyTimer类

package com.vishuo.timer;

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

public class MyTimer {
  public static void main(String[] args) {
//  1.创建一个timer实例
      Timer timer = new Timer();
//  2.创建一个MyTimerTask实例
      MyTimerTask myTimerTask = new MyTimerTask("No.1");
//  3.通过timer定时定频率调用myTimerTask的业务逻辑
      //即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
//    timer.schedule(myTimerTask, 2000L,1000L);

      /*
       * 获取当前时间,并设置成距离当前时间三秒之后的时间
       * 如当前时间是2016-11-10 23:59:57
       * 则设置后的时间则为2016-11-11 00:00:00
       */
      Calendar calendar = Calendar.getInstance();
      SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      System.out.println(sf.format(calendar.getTime()));//获取当前时间
      calendar.add(Calendar.SECOND, 3);//获取当前时间后三秒的时间

//    ______schedule的用法______
      /*
       * 1.在时间等于或超过time的时候执行且仅执行一次task
       * 如在2016-11-11 00:00:00执行一次task:打印任务的名字
       */
//    myTimerTask.setName("schedule1");
//    timer.schedule(myTimerTask, calendar.getTime());

      /*
       * 2.时间等于或超过time时首次执行task
       * 之后每隔period毫秒重复执行一次task
       * 如在2016-11-11 00:00:00第一次执行task:打印任务的名字
       * 之后每隔两秒执行一次task
       */
//    myTimerTask.setName("schedule2");
//    timer.schedule(myTimerTask, calendar.getTime(),2000);

      /*
       * 3.等待delay毫秒后执行且仅执行一次task
       * 如现在是2016-11-11 00:00:00
       * 则在2016-11-11 00:00:00执行一次task:打印任务的名字
       */
//    myTimerTask.setName("schedule3");
//    timer.schedule(myTimerTask, 1000);

      /*
       * 4.等待delay毫秒后首次执行task
       * 之后每隔period毫秒重复执行一次task
       * 如现在是2016-11-11 00:00:00
       * 则在2016-11-11 00:00:00第一次执行task:打印任务的名字
       * 之后每隔两秒执行一次task
       */
//    myTimerTask.setName("schedule4");
//    timer.schedule(myTimerTask, 3000,2000);

//    —————————— scheduleAtFixedRate的用法   ——————————
      /*
       * 1.时间等于或超过time时首次执行task
       * 之后没隔period毫秒重复执行一次task
       * 如在2016-11-11 00:00:00第一次执行task:打印任务名字
       * 之后每隔两秒执行一次task
       */
//    myTimerTask.setName("scheduleAtFixedRate1");
//    timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);

      /*
       * 2.等待delay毫秒首次执行task
       * 之后没隔period毫秒重复执行一次task
       * 如在2016-11-11 00:00:00
       * 则在2016-11-11 00:00:01第一次执行task:打印任务名字
       * 之后每隔两秒执行一次task
       */
      myTimerTask.setName("scheduleAtFixedRate2");
      timer.scheduleAtFixedRate(myTimerTask,3000, 2000);
}
}

三.其他重要函数

TimerTask的cancel(),scheduledExecutionTime()

cancel()

作用:取消当前TimerTask里的任务

代码示例
修改MyTimerTask类,使程序执行三次后,结束任务。上面的MyTimer保持不变,依旧让其运行

myTimerTask.setName("scheduleAtFixedRate2");
timer.scheduleAtFixedRate(myTimerTask,3000, 2000);

MyTimerTask类修改如下:

package com.vishuo.timer;

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

public class MyTimerTask extends TimerTask{
    private String name;
    private Integer count = 0;
    public MyTimerTask(String inputName){
        name=inputName;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        if(count < 3){
            //以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
            //如2016-11-11 00:00:00
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Curren exec time is:"+sf.format(calendar.getTime()));
            //打印当前name的内容
            System.out.println("Current exec name is:"+name);
            count ++;
        }else{
            cancel();
            System.out.println("Task cancel!");
        }
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

scheduledExecutionTime()

作用:返回次任务最近实际执行的已安排执行的时间
返回值:最近发生此任务执行安排的时间,为long型

package com.vishuo.timer;

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

public class MyTimer {
  public static void main(String[] args) {
//  1.创建一个timer实例
      Timer timer = new Timer();
//  2.创建一个MyTimerTask实例
      MyTimerTask myTimerTask = new MyTimerTask("No.1");
//  3.通过timer定时定频率调用myTimerTask的业务逻辑
      //即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
//    timer.schedule(myTimerTask, 2000L,1000L);

      /*
       * 获取当前时间,并设置成距离当前时间三秒之后的时间
       * 如当前时间是2016-11-10 23:59:57
       * 则设置后的时间则为2016-11-11 00:00:00
       */
      Calendar calendar = Calendar.getInstance();
      SimpleDateFormat sf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      System.out.println(sf.format(calendar.getTime()));//获取当前时间
      calendar.add(Calendar.SECOND, 3);//获取当前时间后三秒的时间

      /*
       * scheduledExecutionTime代码示例
       */
      myTimerTask.setName("schedule4");
      timer.schedule(myTimerTask, 3000);
      System.out.println("scheduled time is"+ sf.format(myTimerTask.scheduledExecutionTime()));
}
}

Timer的cancel(),purge()

cancel()

作用:终止此计时器,丢弃所有当前已安排的任务

代码示例:

这里写图片描述

新增CancelTest类

package com.vishuo.timer;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

public class CancelTest {
    public static void main(String[] args) throws InterruptedException {
        // 创建Timer实例
        Timer timer = new Timer();
        // 创建TimerTask实例
        MyTimerTask task1 = new MyTimerTask("task1");
        MyTimerTask task2 = new MyTimerTask("task2");
        //获取当前的执行时间并打印
        Date startTime = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("start time is:"+sf.format(startTime));
        //task1首次执行是距离现在时间3秒后执行,之后每隔2秒执行一次;
        //task2首次执行是距离现在时间1秒后执行,之后每隔2秒执行一次;
        timer.schedule(task1, 3000,2000);
        timer.schedule(task2, 1000,2000);
        //休眠5秒
        Thread.sleep(5000);
        //获取当前的执行时间并打印
        Date cancelTime = new Date();
        System.out.println("cancel time is :"+sf.format(cancelTime));

        //取消所有任务
        timer.cancel();
        System.out.println("Tasks all canceled!");
    }
}

purge()

作用:从此计时器的任务队列中移除所有已取消的任务
返回值:从队列中移除的任务数

演示代码:修改CancelTest类

package com.vishuo.timer;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

public class CancelTest {
    public static void main(String[] args) throws InterruptedException {
        // 创建Timer实例
        Timer timer = new Timer();
        // 创建TimerTask实例
        MyTimerTask task1 = new MyTimerTask("task1");
        MyTimerTask task2 = new MyTimerTask("task2");
        // 获取当前的执行时间并打印
        Date startTime = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("start time is:" + sf.format(startTime));
        // task1首次执行是距离现在时间3秒后执行,之后每隔2秒执行一次;
        // task2首次执行是距离现在时间1秒后执行,之后每隔2秒执行一次;
        timer.schedule(task1, 3000, 2000);
        timer.schedule(task2, 1000, 2000);
        System.out.println("current canceled task number is:"+timer.purge());
        // 休眠5秒
//      Thread.sleep(5000);
        //休眠2秒
        Thread.sleep(2000);
        // 获取当前的执行时间并打印
        Date cancelTime = new Date();
        System.out.println("cancel time is :" + sf.format(cancelTime));

        // 取消所有任务
        // timer.cancel();
        // System.out.println("Tasks all canceled!");

        //取消task2
        task2.cancel();
        System.out.println("current canceled task number is:"+timer.purge());
    }
}

四.schedule和scheduleAtFixedRate的区别

两种情况看区别
1.首次计划执行的时间早于当前的时间
schedule方法:“fixed-delay”;如果第一次执行时间被delay了,随后的执行时间按照上一次实际执行完成的时间点进行计算。

示例代码:

新建DifferenceTest类

package com.vishuo.timer;

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秒前的时间,若当前时间为2016-12-28 00:00:06
        // 那么设置之后时间变成2016-12-28 00:00:00
        calendar.add(Calendar.SECOND, -6);
        Timer timer = new Timer();
        // 第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.schedule(new TimerTask() {

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

scheduleAtFiexedRate方法
“fixed-rate”:如果第一次执行时间被delay了,随后的执行时间按照上一次开始的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步

代码示例:

修改DifferenceTest类

// 第一次执行时间为6秒前,之后每隔两秒钟执行一次
        timer.scheduleAtFixedRate(new TimerTask() {

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

2.任务执行所需时间超出任务的执行周期间隔

schedule方法
下一次执行时间相对于上一次实际执行完成的时间点,因此执行时间会不断延后
代码示例:
修改DifferenceTest类

package com.vishuo.timer;

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秒前的时间,若当前时间为2016-12-28 00:00:06
        // 那么设置之后时间变成2016-12-28 00:00:00
//      calendar.add(Calendar.SECOND, -6);
        Timer timer = new Timer();

        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // TODO Auto-generated method stub
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);
    }
}

scheduleAtFixedRate方法
下一次执行时间相对于上一次开始的时间点,因此执行时间一般不会延后,因此存在并发性
代码示例:修改DifferenceTest类

timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // TODO Auto-generated method stub
                // 打印当前的计划执行时间
                System.out.println("Scheduled exec time is :" + sf.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java定时任务调度工具详解之Timer篇(初级) 的相关文章

  • “java.io.IOException:连接超时”和“SocketTimeoutException:读取超时”之间有什么区别

    如果我设置一个套接字 SoTimeout 并从中读取 当读取时间超过超时限制时 我会收到 SocketTimeoutException 读取超时 这是我的例子中的堆栈 java net SocketTimeoutException Read
  • 带有 Android 支持库 v7 的 Maven Android 插件

    我使用 maven android plugin 构建我的 android 应用程序 它依赖于 android 支持库 v4 和 v7 由于我没有找到如何从developer android com下载整个sdk 因此我无法使用maven
  • Java 7 默认语言环境

    我刚刚安装了 jre7 我很惊讶地发现我的默认区域设置现在是 en US 对于jre6 它是de CH 与jre7有什么不同 默认区域设置不再是操作系统之一吗 顺便说一句 我使用的是Windows7 谢谢你的回答 编辑 我已经看到了语言环境
  • 将SQL数据引入jquery availabletag

    我正在尝试制作自动完成文本框 但如何将 SQL 数据包含到 jquery 可用标记并循环它 我无法根据以下代码执行该功能 任何帮助 将不胜感激 谢谢 这是我的预期输出 预期结果演示 http jsfiddle net VvETA 71 jq
  • 文本在指定长度后分割,但不要使用 grails 打断单词

    我有一个长字符串 需要将其解析为长度不超过 50 个字符的字符串数组 对我来说 棘手的部分是确保正则表达式找到 50 个字符之前的最后一个空格 以便在字符串之间进行彻底的分隔 因为我不希望单词被切断 public List
  • 删除优先级队列的尾部元素

    如何删除优先级队列的尾部元素 我正在尝试使用优先级队列实现波束搜索 一旦优先级队列已满 我想删除最后一个元素 优先级最低的元素 Thanks 没有简单的方法 将元素从原始元素复制到新元素 最后一个除外 PriorityQueue remov
  • 从 MS Access 中提取 OLE 对象(Word 文档)

    我有一个 Microsoft Access 数据库 其中包含一个包含 Microsoft Word 文档的 OLE 对象字段 我试图找到代码来检索保存在 OLE 对象中的文件 以便用户可以从我的 JavaFx 应用程序中的按钮下载它 但没有
  • 如何检测图像是否像素化

    之前有人在 SO 上提出过这样的问题 在Python中检测像素化图像 https stackoverflow com questions 12942365 detecting a pixelated image in python还有关于q
  • 在 MongoDB 和 Apache Solr 之间同步数据的简单方法

    我最近开始使用 MongoDB 和 Apache Solr 我使用 MongoDB 作为数据存储 并且希望 Apache Solr 为我的数据创建索引 以实现应用程序中的搜索功能 经过一些研究 我发现 基本上有两种方法可以在 MongoDB
  • org/codehaus/plexus/archiver/jar/JarArchiver(不支持的major.minor版本49.0)-Maven构建错误

    下午大家 我在尝试构建项目时收到上述错误 我很确定这与使用 Java 1 6 编译的 Maven 最新更新有关 而我们尝试构建的项目是 1 4 项目 在此之前的插件工作没有问题 因此我将以下内容添加到 POM xml 文件中以尝试强制使用现
  • 从休眠乐观锁定异常中恢复

    我有一个这样的方法 Transactional propagation Propagation REQUIRES NEW public void doSomeWork Entity entity dao loadEntity do some
  • 添加到列表时有没有办法避免循环?

    我想知道这样的代码 List
  • 当 minifyEnabled 为 true 时 Android 应用程序崩溃

    我正在使用多模块应用程序 并且该应用程序崩溃时minifyEnabled true in the installed模块的build gradle 以下是从游戏控制台检索到的反混淆堆栈跟踪 FATAL EXCEPTION Controlle
  • 我们如何测试包私有类?

    我正在看书Effective Java in Item 13 Minimize the accessibility of classes and members 它提到 为了方便测试 您可能想让类 接口或成员更易于访问 这在某种程度上是好的
  • Play.application() 的替代方案是什么

    我是 Play 框架的新手 我想读取conf文件夹中的一个文件 所以我用了Play application classloader getResources Data json nextElement getFile 但我知道 play P
  • Karaf / Maven - 无法解决:缺少需求 osgi.wiring.package

    我无法在 Karaf 版本 3 0 1 中启动捆绑包 该包是使用 Maven 构建的并导入gson http mvnrepository com artifact com google code gson gson 2 3 1 我按照要求将
  • 我可以限制分布式应用程序发出的请求吗?

    我的应用程序发出 Web 服务请求 提供商处理的请求有最大速率 因此我需要限制它们 当应用程序在单个服务器上运行时 我曾经在应用程序级别执行此操作 一个对象跟踪到目前为止已发出的请求数量 并在当前请求超出允许的最大负载时等待 现在 我们正在
  • 如何让 Emma 或 Cobertura 与 Maven 一起报告其他模块中源代码的覆盖率?

    我有一个带有 Java 代码的多模块 Maven 设置 我的单元测试在其中一个模块中测试多个模块中的代码 当然 这些模块具有相互依赖性 并且在测试执行之前根据需要编译所有相关模块中的代码 那么 如何获得整个代码库覆盖率的报告 注意 我不是问
  • JMS 中的 MessageListener 和 Consumer 有什么区别?

    我是新来的JMS 据我了解Consumers能够从队列 主题中挑选消息 那么为什么你需要一个MessageListener因为Consumers会知道他们什么时候收到消息吗 这样的实际用途是什么MessageListener 编辑 来自Me
  • HttpClient请求设置属性问题

    我使用这个 HttpClient 库玩了一段时间 几周 我想以某种方式将属性设置为请求 不是参数而是属性 在我的 servlet 中 我想使用 Integer inte Integer request getAttribute obj 我不

随机推荐