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篇(初级) 的相关文章

随机推荐