zoukankan      html  css  js  c++  java
  • Java——定时任务调度工具


    一、什么是定时任务调度?

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

    1、常用的定时调度工具:Timer和Quartz

    对时间的控制上,能实现简单的定时任务。

    若特定时间的定时任务,需要用Quartz,它的定时机制更加庞大。

    Quartz可以使用多个执行线程来实现。

    二、Timer简介

    1、Timer的定义以及架构

    Timer定义:java.lang.object,是java.util.Timer包下。

    一个后台的线程,后台线程支持多个目录定时执行。

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

    主要构件:

    Timer——>定时调用——>TimerTask(业务线程)。

    Timer

    TimerThread后台执行的线程。

    TimerTask对应的业务线程, TimerThread通过定期的调用TimerTask的run方法来实现定时调度。

    2、Timer示例

    import java.util.TimerTask;
    
    public class MytimerTask extends TimerTask{
        private String name;
        //添加name的set和get方法
        public MyTimerTask(String inputname){
            name=inputname;
        }
    
        @Override
        public void run(){
            //打印输出内容:
            out.print("test"+name);
        }
    }
    public class Mytimer{
    
        public static void main(String[] args){
            //1:创建一个timer实例
            Timer timer = new Timer();
            //2:创建一个MyTimerTask实例
            MyTimeTask myTimerTask = new MyTimerTask("No.1");
            //3:通过timer定时定频率调用MyTimerTask的业务逻辑
            //即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
            timer.schedule(myTimerTask,2000L,1000L);
        }
    }

    三、Timer的定时调度函数

    1、schedule的四种用法

    ①、chedule(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。

    import java.util.TimerTask;
    
    public class MytimerTask extends TimerTask{
        private String name;
        //添加name的set和get方法
        public MyTimerTask(String inputname){
            name=inputname;
        }
    
        @Override
        public void run(){
            //以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //打印当前执行时间
            out.print("当前时间:"+sf.format(calendar.getTime()));
    
    
            //打印name:
            out.print("test"+name);
        }
    }
    public class Mytimer{
    
        public static void main(String[] args){
            //1:创建一个timer实例
            Timer timer = new Timer();
            //2:创建一个MyTimerTask实例
            MyTimeTask myTimerTask = new MyTimerTask("No.1");
            //3:通过timer定时定频率调用MyTimerTask的业务逻辑
            //即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次
            //timer.schedule(myTimerTask,2000L,1000L);
    
    
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //打印当前执行时间
            out.print("当前时间:"+sf.format(calendar.getTime()));
            //设置3秒之后的时间
            calendar.add(Calendar.SECOND,3);
    
            //schedule的用法
            /**
            * 1、在时间等于或超过time的时候执行且仅执行一次task
            /
    
            myTimerTask.setName("schedule1");
            timer.schedule(myTimerTask,calendar.getTime());
    
            /**
            *2、时间等于或超过time时首次执行task
            *之后每隔period毫秒重复执行一次task
            /
            myTimerTask.setName("schedule2");
            //每隔2秒钟,重复执行myTimerTask方法中的run方法
            timer.schedule(myTimerTask,calendar.getTime(),2000);
        }
    
            /**
            *3、等待delay毫秒后执行且仅执行一次task
            *如现在是00:00:00
            *则在00:00:01执行一次task,打印任务的名字
            /
            myTimerTask.setName("schedule3");
            timer.schedule(myTimerTask,1000);
    
            /**
            *4、等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task
            /
            myTimerTask.setName("schedule4");
            timer.schedule(myTimerTask,3000,2000);
    
    }

    2、scheduleAtFixedRate的两种用法

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

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

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

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

        /**
        *1、时间等于或超过timer时首次执行task,之后每隔period毫秒重复执行一次task
        /
        myTimerTask.setName("scheduleAtFixedRate1");
        timer.scheduleAtFixedRate(myTimerTask,calendar.getTime(),2000);
    
        /**
        *2、等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task  
        /
        myTimerTask.setName("scheduleAtFixedRate2");
        timer.scheduleAtFixedRate(myTimerTask,3000,2000);

    四、其他重要函数

    1、TimerTask的cancel(),scheduleExecutionTime()

    cancel():

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

    //计时器
    private Integer count=0;
    
    void run(){
        if(count < 3){
            //业务
    
            count++;
        }else{
            //任务取消
            cancel();
        }
    }

    scheduleExecutionTime():

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

        myTimerTask.setName("schedule");
        timer.scheduleAtFixedRate(myTimerTask,3000);
        out.print("test":sf.format(myTimerTask.scheduleExecutionTime()));

    2、Timer的cancel(),purge()

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

        //休眠5秒
        Thread.sleep(5000);
        //取消当前所有任务
        timer.calcel();

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

        timer.schedule(task2,1000,2000);
        timer.purge();
    
        Thread.sleep(2000);
        Date cancelTimer = new Date();
        task2.cancel();

    五、schedule与schduleAtFixedRate的区别

    1、区别:首次计划执行的时间早于当前的时间

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

    void main(String[] args){
        //规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat(yy:MM:dd mm:HH:ss)
        //获取当前时间
        Calendar calendar = Caledndar.getInstance();
        out.print("sf.format(calendar.getTime()));
        //设置成6秒前的时间,若当前时间为 00:00:06,
        //那么设置之后时间变成00:00:00
        calendar.add(Calendar.SECOND,-6);
        Timer timer = new Timer();
        //第一次执行时间为6秒前,之后每隔2秒钟执行一次
        timer.schedule(new TimerTask(){
            public void run(){
                //打印当前的计划执行时间
                out.print("test:"+sf.format(scheduleExecutionTimer()));
            }
        },calendar.getTimer(),2000);
    }

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

        timer.schduleAtFixedRate(new TimerTask(){
            public void run(){
                //打印当前的计划执行时间
                out.print("test:"+sf.format(scheduleExecutionTimer()));
            }
        },calendar.getTimer(),2000);

    2、区别:任务执行所需时间超过任务的执行周期间隔

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

    void main(String[] args){
        //规定时间格式
        final SimpleDateFormat sf = new SimpleDateFormat(yy:MM:dd mm:HH:ss)
        //获取当前时间
        Calendar calendar = Caledndar.getInstance();
        out.print("sf.format(calendar.getTime()));
        Timer timer = new Timer();
        //第一次执行时间为6秒前,之后每隔2秒钟执行一次
        timer.schedule(new TimerTask(){
            public void run(){
                try{
                    Thread.sleep(3000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                //打印当前的计划执行时间
                out.print("test:"+sf.format(scheduleExecutionTimer()));
            }
        },calendar.getTimer(),2000);
    }

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

    timer.schduleAtFixedRate(new TimerTask(){
            public void run(){
                try{
                    Thread.sleep(3000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                //打印当前的计划执行时间
                out.print("test:"+sf.format(scheduleExecutionTimer()));
            }
        },calendar.getTimer(),2000);

    六、Timer的缺陷

    1、管理并发任务的缺陷

    Timer有且仅有一个后台的线程,并不支持任务与任务之间的并发;如果存在多个任务,且任务时间过长,会导致执行效果与预期不符;

    第二个任务会在第一个任务执行完成后在执行自己的任务;

    2、当任务抛出异常时的缺陷

    如果 TimerTask抛出RuntimeException,Timer会停止所有任务的运行;

        throw new RuntiomeException();  

    第一个任务如果抛出异常,则第二个任务就不会再继续执行了,直接从第一个任务开始终止执行;

    3、Timer的使用禁区:

    对时效性要求较高的多任务并发作业:

    对复杂任务的调度;

  • 相关阅读:
    JDBC基本入门-JDBC中各个接口和类详解
    Docker 安装与基本使用
    java打包和运行的方式
    使用@Valid+BindingResult进行controller参数校验
    Antd使用timePicker封装时间范围选择器(React hook版)
    antd的table组件设置Column的width列宽度不生效问题
    vector二维数组如何排序
    递归反转链表(通俗详解)
    安装pythorch出现“由于目标计算机积极拒绝,无法连接”问题
    C语言字符串
  • 原文地址:https://www.cnblogs.com/aixing/p/13327530.html
Copyright © 2011-2022 走看看