博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java定时任务调度工具Timer
阅读量:6812 次
发布时间:2019-06-26

本文共 7009 字,大约阅读时间需要 23 分钟。

hot3.png

前言:

首先我们先明确一下什么是定时任务调度?

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

Java中定时任务调动工具有俩:Timer 、Quartz

区别:

    出身不同:Timer由jdk直接提供,不需jar包支持;Quartz需引入jar包。

    能力不同:Timer简单定时任务;Quartz时间控制功能更强大。

    底层机制:Timer只有一个后台线程执行;Quartz是多线程执行任务。

一.Timer简介:

    让我们看下官方文档api(JDK1.8)

172519_i6su_3700425.png

可能有的小伙伴英语水平不太好,那让我们看下中文版吧:

 

172143_Py0o_3700425.png

那么我们可以归纳Timer的定义:有且仅有一个后台线程对多个业务线程进行定时定频率的调度

主要构件:

172935_zg4G_3700425.png

 

Timer工具类详解:

173200_bAJV_3700425.png

二.Timer实战

1.简单实战

1)定时任务类

package com.leo.timer;import java.util.TimerTask;public class MyTimerTask extends TimerTask {    private String name;    public MyTimerTask(String inputName){        name=inputName;    }    @Override    public void run() {        //打印当前name的内容        System.out.println("Current exec name is"+name);    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

2)Timer启动

package com.leo.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);    }}

控制台打印显示:

204722_dwNX_3700425.png

 

2.Timer的定时调度函数

1)schedule的四种用法

    1.schedule(task,time)

        作用:在时间等于或超过time的时候执行且仅执行一次task

    2.schedule(task,time,period)

        参数:    task-所要安排的任务

                      time-首次执行任务的时间

                      period-执行一次task的时间间隔,单位是毫秒

    3.schedule(task,delay)

        参数:    task-所要安排的任务

                      delay-执行任务前的延迟时间,单位是毫秒

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

    4.schedule(task,delay,period)

        参数:    task-所要安排的任务

                      delay-执行任务前的延迟时间,单位是毫秒

                      period-执行一次task的时间间隔,单位是毫秒

        作用:    等待delay毫秒后执行且仅执行一次task,之后每隔period毫秒重复执行一次task

具体代码如下:

    定时任务类:

    

package com.leo.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() {        //打印当前name的内容        System.out.println("Current exec name is "+name);        //以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间        Calendar calendar=Calendar.getInstance();        SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        System.out.println("Current exec time is"+sf.format(calendar.getTime()));    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

    四中启动类:

        

package com.leo.timer;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Timer;public class MyTimer {    public  static void  main(String[] args){        //一.创建一个timer实例        Timer timer=new Timer();        //二.创建一个MyTimerTask实例        MyTimerTask myTimerTask=new MyTimerTask("No.1");        //三.通过timer定时频率调用myTImerTask的业务逻辑        // 既第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次        //timer.schedule(myTimerTask,2000L,1000L);        /**         * 获取当前时间,并设置成距离当前时间三秒之后的时间         * 如果当前时间是2017-10-21 23:59:57         * 则设置后的时间则为2017-10-22 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);        /**         * 1.  schedule(task,time)         *      在时间等于或超过time的时候执行且仅执行一次task         *      如在2017-10-22 00:00:00 执行一次task:打印任务的名字         */        //myTimerTask.setName("schedule1");        //timer.schedule(myTimerTask,calendar.getTime());        /**         * 2. schedule(task,time,period)         *      时间等于或超过time时首次执行task         *      之后每隔period毫秒重复执行一次task         *      如在2017-10-22 00:00:00 第一次执行task:打印任务的名字         *      之后每隔两秒执行一次task         */        //myTimerTask.setName("schedule2");        //timer.schedule(myTimerTask,calendar.getTime(),2000);        /**         * 3. schedule(task,delay)         *      等待delay毫秒后执行且仅执行一次task         *      如现在是2017-10-22 00:00:00         *      则在2017-10-22 00:00:01执行一次task::打印任务的名字         */        //myTimerTask.setName("schedule3");        //timer.schedule(myTimerTask,1000);        /**         * 4.  schedule(task,delay,period)         *      等待delay毫秒后首次执行task         *      如现在是2017-10-22 00:00:00         *      则在2017-10-22 00:00:01执行一次task::打印任务的名字         *      之后每隔两秒执行一次task         */         myTimerTask.setName("schedule4");         timer.schedule(myTimerTask,calendar.getTime(),2000);    }}

2)scheduleAtFixedRate的四种用法           

    1.scheduleAtFixedRate(task,time,period)

        参数:    task-所要安排的任务

                      time-首次执行任务的时间

                      period-执行一次task的时间间隔,单位是毫秒    

       作用:    时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task(和schedule的第二种用法是一样的)

    2.scheduleAtFixedRate(task,delay,period)

        参数:    task-所要安排的任务

                      delay-执行任务前的延迟时间,单位是毫秒

                      period-执行一次task的时间间隔,单位是毫秒

        作用:    等待delay毫秒后执行且仅执行一次task,之后每隔period毫秒重复执行一次task(和schedule的第四种用法是一样的)

代码:

//----------------scheduleAtFixedRate的用法-------------------------------        /**         * 1 . scheduleAtFixedRate(task,time,period)         *      时间等于或超过time时首次执行task         *      之后每隔period毫秒重复执行一次task         *      如在2017-10-22 00:00:00 第一次执行task:打印任务的名字         *      之后每隔两秒执行一次task         */        //myTimerTask.setName("scheduleAtFixedRate1");        //timer.scheduleAtFixedRate(myTimerTask,calendar.getTime(),2000);        /**         * 2.  scheduleAtFixedRate(task,delay,period)         *      等待delay毫秒后首次执行task         *      如现在是2017-10-22 00:00:00         *      则在2017-10-22 00:00:01执行一次task::打印任务的名字         *      之后每隔两秒执行一次task         */        myTimerTask.setName("scheduleAtFixedRate2");        timer.scheduleAtFixedRate(myTimerTask,3000,2000);

 

我们先来看Timer的其他重要函数,下一标题再具体讲解schedule和schedulAtFixedRate二者的不同

3)其他重要函数

    1.TimerTask的cancel(),scheduledExecutionTime() :

        cancel:

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

        

@Override    public void run() {        if (count<3){            //打印当前name的内容            System.out.println("Current exec name is "+name);            //以yyyy-MM-dd HH:mm:ss的格式打印当前执行时间            Calendar calendar=Calendar.getInstance();            SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            System.out.println("Current exec time is"+sf.format(calendar.getTime()));            count++;        }else {            cancel();            System.out.println("Task cancel");        }    }

        scheduledExecutionTime():

            作用:返回此任务最近实际执行的已安排执行的时间

 

    2.Timer的cancel() , perge() :

        cancel():

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

        233606_ynFl_3700425.png

        purge():

            作用:从此计时器的任务队列中移除所要已取消的任务

            返回值:从队列中移除的任务数

234105_l0Fd_3700425.png

3.schedule和scheduleAtFixeRate的区别

1)首次计划执行的时间早于当前的时间

    1.schedule方法:

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

000358_MkvD_3700425.png

console:

000556_8RYO_3700425.png

    2.scheduleAtFixedRate方法:

            "fixed-rate"如果第一次执行时间被delay了,随后的执行时间按上一次实际执行完成的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步

001121_I684_3700425.png

console:

001158_cyfJ_3700425.png

 

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

    1.schedule方法:

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

002010_eqXy_3700425.png

console:

002047_fK7f_3700425.png

    2.scheduleAtFixedRate方法:

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

002322_VjSr_3700425.png

console:

002415_XfgL_3700425.png

4.Timer的缺陷:

1)管理并发任务的缺陷

    Timer有且仅有一个线程去执行定时任务,如果存在多个定时任务,且任务时间过长,会导致执行效果与预期不符

003147_z6tn_3700425.png

003228_G3df_3700425.png

console:

003345_p8CL_3700425.png

同样scheduleAtFixedRate也不能解决并发问题:

003506_ljLB_3700425.png

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

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

三.Timer的使用禁区:

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

2.对复杂的任务的调度

如果想要满足以上功能,需用到Quartz

 

 

 

 

 

 

转载于:https://my.oschina.net/u/3700425/blog/1554422

你可能感兴趣的文章
遇到的情况记录
查看>>
Django ORM那些相关操作
查看>>
大白话5分钟带你走进人工智能-第一节开篇介绍以及线性回归简介篇
查看>>
Hive篇--搭建Hive集群
查看>>
Javascript小括号“()”的多义性
查看>>
mokoid android open source HAL hacking in a picture
查看>>
Servlet
查看>>
Effective Java 学习笔记之二
查看>>
css3技巧——产品列表之鼠标滑过效果(一)
查看>>
如何让git小乌龟工具TortoiseGit记住你的账号密码
查看>>
网络对抗技术作业一
查看>>
SDUT OJ[3109] 买买买 背包 dp
查看>>
SQL 注入防御方法总结
查看>>
fiddler使用
查看>>
kqueue epoll 边界触发模式的网络编程模型
查看>>
每天一道算法题(16)——翻转链表
查看>>
my vim IDE 编辑器的配置
查看>>
Jenkins持续集成学习-搭建jenkins问题汇总
查看>>
Print 与Debug.Log的区别
查看>>
Servlet各种接口和类
查看>>