Java定时调度任务详解之Timer篇

来源:互联网 发布:乌鲁木齐网络架构师 编辑:程序博客网 时间:2024/06/13 23:58

简单介绍

什么是定时任务调度

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

Java中定时调度工具

    Timer  ---〉 jdk
    Quartz --〉 第三方jar包,实现更完善。
    尽量使用jdk提供的timer

Timer简介

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

主要构件


    Timer 可以理解为每个后台执行的线程,TimerTask业务线程

Timer工具类详解



第一个简单实例

import java.util.TimerTask;public class MyTaskTimer extends TimerTask {private String name;public MyTaskTimer(String name) {this.name = name;}@Overridepublic void run() {            System.out.println("Current name is: " + name);}public String getName() {return name;}public void setName(String name) {this.name = name;}}
测试类
import java.util.Timer;public class MyTimer {public static void main(String[] args) {// 1、创建一个Timer实例Timer timer = new Timer();//2、创建一个MyTimerTask实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");//3、通过timer定时定频率调用myTimerTask的业务逻辑// 即第一次执行是在当前时间的两秒之后,之后每隔一秒钟执行一次timer.schedule(myTaskTimer, 2000L, 1000L);}}

Timer的定时调度函数

schedule(task, time)

    task --> 所要安排的任务
    在时间等于或超过time的时候执行且仅执行一次task

实例

import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.TimerTask;public class MyTaskTimer extends TimerTask {private String name;public MyTaskTimer(String name) {this.name = name;}@Overridepublic void run() {        Calendar calendar = Calendar.getInstance();        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        System.out.println("current exect time:" + sf.format(calendar.getTime()));System.out.println("Current name is: " + name);}public String getName() {return name;}public void setName(String name) {this.name = name;}}

测试类
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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("schedule1");timer.schedule(myTaskTimer, calendar.getTime());}}

schedule(task, time, period)

    task     --> 所要安排的任务
    time     -->首次执行任务的时间
    period  -->执行一次task的时间间隔,单位是毫秒
    时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task

测试类

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("schedule2");timer.schedule(myTaskTimer, calendar.getTime(), 2000);//执行3秒钟之后的时间}}

schedule(task, delay)

    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    等待delay毫秒后执行且仅执行一次task

实例

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("schedule3");timer.schedule(myTaskTimer, 2000);//执行3秒钟之后的时间}}

schedule(task, delay, period)

    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    period  -->执行一次task的时间间隔,单位是毫秒
    等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task

实例

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");
/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */myTaskTimer.setName("schedule4");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);//设置三秒之后的时间myTaskTimer.setName("schedule4");timer.schedule(myTaskTimer, 2000, 2000);//执行3秒钟之后的时间}}

scheduleAtFixedRate的两种用法

scheduleAtFixedRate(task, time, period)

    task     --> 所要安排的任务
    time     -->首次执行任务的时间
    period  -->执行一次task的时间间隔,单位是毫秒
    时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task

实例

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("scheduleAtFixedRate1");timer.scheduleAtFixedRate(myTaskTimer, calendar.getTime(), 2000);//执行3秒钟之后的时间}}

scheduleAtFixedRate(task, delay, period)

    task   --> 所要安排的任务
    delay --> 执行任务前的延时时间,单位毫秒
    period  -->执行一次task的时间间隔,单位是毫秒
    等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task

实例

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("scheduleAtFixedRate2");timer.scheduleAtFixedRate(myTaskTimer, 3000, 2000);//距离当前时间3秒钟}}

其它重要函数

cancel()

取消当前TimerTask里的任务

实例

import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.TimerTask;public class MyTaskTimer extends TimerTask {private String name;private Integer count = 0;public MyTaskTimer(String name) {this.name = name;}@Overridepublic void run() {if (count < 3) {Calendar calendar = Calendar.getInstance();                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");                System.out.println("current exect time:" + sf.format(calendar.getTime()));System.out.println("Current name is: " + name);count ++;} else {cancel();System.out.println("Task Cancle");}        }public String getName() {return name;}public void setName(String name) {this.name = name;}}

测试类

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("schedule");timer.schedule(myTaskTimer, 3000, 2000);//距离当前时间3秒钟}}

scheduleExecutionTime()

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

实例

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实例MyTaskTimer myTaskTimer = new MyTaskTimer("No 1");/** * 获取当前时间,并设置成距离当前时间三秒之后的时间 */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);//设置三秒之后的时间myTaskTimer.setName("schedule");timer.schedule(myTaskTimer, 3000);//距离当前时间3秒钟,只执行一次System.out.println("schedule time is :" + sf.format(myTaskTimer.scheduledExecutionTime()));}}

Timer下的cancel()

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

实例:

import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;public class CancleTest {public static void main(String[] args) throws InterruptedException {//创建一个Timer实例Timer timer = new Timer();//创建TaskTimer实例MyTaskTimer task1 = new MyTaskTimer("task1");MyTaskTimer task2 = new MyTaskTimer("task2");//获取当前时间并打印Date startDate = new Date();                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("start time is :" + sf.format(startDate));timer.schedule(task1, 3000L, 2000L);timer.schedule(task2, 1000L, 2000L);//休眠5秒Thread.sleep(5000L);//获取当前时间并打印Date cancelTime = new Date();System.out.println("cancel time is :" + sf.format(cancelTime));//取消所有任务timer.cancel();System.out.println("Tasks all canceled");}}

Timer下的purge()

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

实例

import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;public class CancleTest {public static void main(String[] args) throws InterruptedException {//创建一个Timer实例Timer timer = new Timer();//创建TaskTimer实例MyTaskTimer task1 = new MyTaskTimer("task1");MyTaskTimer task2 = new MyTaskTimer("task2");//获取当前时间并打印Date startDate = new Date();                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("start time is :" + sf.format(startDate));timer.schedule(task1, 3000L, 2000L);timer.schedule(task2, 1000L, 2000L);System.out.println("current canceled task number is:" + timer.purge());//休眠2秒Thread.sleep(2000L);//获取当前时间并打印Date cancelTime = new Date();System.out.println("cancel time is :" + sf.format(cancelTime));//取消task2的任务task2.cancel();System.out.println("current canceled task number is:" + timer.purge());}}

schedule和scheduleAtFixRate区别

schedule方法

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

实例

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秒的时间,若当前时间为2017-11-11 00:00:06//那么设置之后的时间变成2017-11-11 00:00:00calendar.add(Calendar.SECOND, -6);Timer timer = new Timer();//第一次执行时间为6秒前,之后每隔两秒钟执行一次timer.schedule(new TimerTask() {@Overridepublic void run() {//打印当前计划执行时间System.out.println("schedule exect time is:" + sf.format(scheduledExecutionTime()));System.out.println("Task is being exected");}},calendar.getTime(), 2000L);}}

scheduleAtFixRate方法

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

任务执行时间超出执行时间间隔

schedule方法
    下一次执行时间相对于上一次实际执行完成的是时间点,因此执行时间会不断延后。
实例
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()));Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {try {Thread.sleep(3000L);} catch (InterruptedException e) {e.printStackTrace();}//打印当前计划执行时间System.out.println("schedule exect time is:" + sf.format(scheduledExecutionTime()));System.out.println("Task is being exected");}},calendar.getTime(), 2000L);}}
scheduleAtFixRate方法
    下一次执行时间相对于上一次开始的时间点,因此执行时间不会延后,因此存在并发性。

实际应用

import java.text.SimpleDateFormat;import java.util.TimerTask;/** * 跳舞机器人,每隔两秒钟跳舞 */public class DancingRobot extends TimerTask {@Overridepublic void run() {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("Scheduled exec time is : "+ sf.format(scheduledExecutionTime()));System.out.println("Dancing happily");}}
import java.util.Timer;import java.util.TimerTask;/** * 灌水机器人,水注入满5升后,等待两秒钟后,取消所有 * @author lijingyu * */public class WaterRobot extends TimerTask {private Timer timer;private Integer bucketCapacity = 0;public WaterRobot(Timer inputTimer) {timer = inputTimer;}@Overridepublic void run() {if (bucketCapacity < 5) {System.out.println("Add 1L water into the bucket!");bucketCapacity ++;} else {System.out.println("The number of canceled task in timer is :" + timer.purge());//水满后停止cancel();System.out.println("The WaterRobot has bean aborted!");System.out.println("The number of canceled task in timer is :" + timer.purge());System.out.println("Current water is " + bucketCapacity + "L");try {Thread.sleep(2000L);} catch (InterruptedException e) {e.printStackTrace();}timer.cancel();//取消所有}}}
执行机器人
import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Timer;public class ExectorRobot {public static void main(String[] args) {Timer timer = new Timer();//获取当前时间Calendar calendar = Calendar.getInstance();SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("Current time is" + sf.format(calendar.getTime()));DancingRobot dr = new DancingRobot();WaterRobot wr = new WaterRobot(timer);timer.schedule(dr, calendar.getTime(), 2000L);timer.scheduleAtFixedRate(wr, calendar.getTime(), 1000L);}}

Timer缺陷

管理并发任务的缺陷

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

当任务抛出异常时缺陷

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

Timer的使用禁区

    对时效性要求较高的多任务并发作业;对复杂的任务调度。

参考

    慕课网

原创粉丝点击