Timer 的缺陷:
1 并发操作时的缺陷,这是因为 Timer 的后台只有一个执行线程导致的。
2 当任务抛出异常时的缺陷。如果 TimeTask 抛出 RuntimeException,Timer 会停止所有任务的执行。
根据缺陷,我们可以得出 Timer 的使用禁区。
1 对时效性要求较高的多任务并发作业,虽然 Timer 支持多任务执行,但那都是串行执行的。
2 对复杂的任务的调度,因为在复杂的任务中可能会出现异常,而Timer 中一旦出现异常,则停止执行。
schedule与scheduleAtFixedRate的区别
情况1:计划执行的时间早于当前的时间。
schedule方法:当调用该方法时,调用定时任务的时间以当前时间为准,可以通过调用scheduleExecutionTime查看时间的基准。(设置了00:00开始执行,每两秒钟执行一次,但是任务开始的时候是00:06,那么就会执行00:06 00:08 )
scheduleAtFixedRate():调用该方法时,以方法中传入的时间为准,例如,传入的时间为12:00,那么scheduleExecutionTime()的时间就是12:00,如果当前时间晚于传入的时间,那么就会进行追赶多次执行该方法。注意:它存在并发性,例如图片中当前时间为15:05:31,但是调用定时任务的时间为15:05:25,那么它就会在同一时间执行三次该方法。 25 27 29 31,25 27 29是一瞬间执行
情况2:任务执行所需时间超出任务执行的时间间隔。
schedule方法:比如规定2s执行一次,但是执行需要3s,那么schedule(timeTask,calender.getTime(),2000),就会在设置的calender中执行一次,以及3s后执行一次
scheduleAtFixRate(): 比如规定2s执行一次,但是执行需要3s,那么schedule(timeTask,calender.getTime(),2000),就会在设置的calender中执行一次,以及2s后执行一次,存在并发性
TimerTask的cancel()函数的作用:取消当前TimerTask里的任务
TimerTask的scheduleExecutionTime()作用:返回此任务最近实际执行的已安排执行的时间,返回值:最近发生此任务执行安排的时间,为long型
Timer的cancel()函数的作用:终止此计时器,丢弃所有当前已安排的任务
Timer的purge()函数的作用:从此计时器的任务队列中移除所有已取消的任务。返回值:从队列中移除的任务数。
Timer的schedule方法的四种用法:
1、schedule(TimerTask task,Date time):在时间等于time或超过time执行且执行一次task(task业务线程,time时间)。在time或超过time的时候执行一次,且只执行一次
2、schedule(TimerTask task,Date time,long period):前两个参数和1一样,这里第三个参数表示每隔多长时间该任务调度线程调用业务线程。在time的时候执行一次,之后每间隔period就会执行一次
3、schedual(TimerTask task,long delay):延迟当前时间多少秒之后执行该定时任务,并且仅执行一次。
4、schedual(TimerTask task,long delay,long period):延迟当前时间delay秒之后执行定时任务,并且每隔period执行一次定时任务。
Timer的scheduleAtFixedRate的两种用法:
1、scheduleAtFixedRated(TimerTask task,Date date,long period):到date指定时间每隔period执行一次定时任务task。
2、scheduleAtFixedRated(TimerTask task,long delay,long period):延迟当前时间delay毫秒后每隔period时间执行一次定时任务。
TimerThread是后台执行的线程;TimerTask对应的是业务线程,run()中涵盖了业务的逻辑。TimerThread通过定期调用队列里的TimerTask的run()方法,来实现对任务的定时定频率的调度。我们只需要关注Timer和TimerTask。TimerThread和TaskQueue都是透明的。
定时任务调度:基于给定的时间点,给定的时间间隔,给定的执行次数自动执行的任务。Java中的定时任务1、Timer2、QuartzTimer和Quartz的区别:1、Timer由jdk提供,调用简单,不要需要导入jar包。而Quartz需要导入jar包,不是jdk自带。2、Quartz的功能比Timer的功能强大完善。3、Timer后台执行一个线程来完成定时任务,Quartz可以在后台执行多个线程来完成定时任务。
TimerThread是后台执行的线程;TimerTask对应的是业务线程,run()中涵盖了业务的逻辑。
TimerThread通过定期调用队列里的TimerTask的run()方法,来实现对任务的定时定频率的调度。
我们只需要关注Timer和TimerTask。TimerThread和TaskQueue都是透明的。
Timer的缺陷
1、管理并发任务的缺陷:Timer有且仅有一条后台的线程,对定时任务定时定频率的调用,对于多任务来说并不支持任务与任务之间的并发。
例如:
2、任务抛出异常的缺陷:它对runtimeexception的支持不是很好。
举例:
schedule与scheduleAtFixedRate的区别
情况1:计划执行的时间早于当前的时间。
schedule方法:当调用该方法时,调用定时任务的时间以当前时间为准,可以通过调用scheduleExecutionTime查看时间的基准。
scheduleAtFixedRate():调用该方法时,以方法中传入的时间为准,例如,传入的时间为12:00,那么scheduleExecutionTime()的时间就是12:00,如果当前时间晚于传入的时间,那么就会进行追赶多次执行该方法。注意:它存在并发性,例如图片中当前时间为15:05:31,但是调用定时任务的时间为15:05:25,那么它就会在同一时间执行三次该方法。
情况2:任务执行所需时间超出任务执行的时间间隔。
schedule()
scheduleAtFixedTime()
TimerTask的cancel()、scheduledExecutionTime()
cancel():取消当前TimerTask里的任务。
scheduledExecutionTime():返回最近一次执行该定时任务的时间。
Timer的cancel()、purge()
cancel():Timer下的cancel()表示结束当前Timer的所有定时任务。
purge():表示从此Timer的定时任务队列中移除所有已经取消的定时任务,并且返回移除的个数。
Timer的schedule方法的四种用法:
1、schedule(TimerTask task,Date time):在时间等于time或超过time执行且执行一次task(task业务线程,time时间)。
2、schedule(TimerTask task,Date time,long period):前两个参数和1一样,这里第三个参数表示每隔多长时间该任务调度线程调用业务线程。
3、schedual(TimerTask task,long delay):延迟当前时间多少秒之后执行该定时任务,并且仅执行一次。
4、schedual(TimerTask task,long delay,long period):延迟当前时间delay秒之后执行定时任务,并且每隔period执行一次定时任务。
Timer的scheduleAtFixedRate的两种用法:
1、scheduleAtFixedRated(TimerTask task,Date date,long period):到date指定时间每隔period执行一次定时任务task。
2、scheduleAtFixedRated(TimerTask task,long delay,long period):延迟当前时间delay毫秒后每隔period时间执行一次定时任务。
Timer定义:java.util.Timer包,有且仅有一个后台线程对多个业务线程进行定时定频率的调度。
Timer(调度线程)——》TimerTask(业务线程)
Timer工具类详解:如图,这里可以理解TimerThread是后台定时调用的线程,而TimerTask可以理解为业务线程,业务线程要在run方法中进行实现。
举例:如图,业务线程的实现需要在继承TimerTask的run方法中实现,调度业务线程需要通过Timer实例的schedule方法,参数1表示业务线程所在类实例,参数2表示起初隔多长时间执行该调度线程,参数3表示每个多长时间间隔执行业务线程。
定时任务调度:基于给定的时间点,给定的时间间隔,给定的执行次数自动执行的任务。
Java中的定时任务
1、Timer
2、Quartz
Timer和Quartz的区别:
1、Timer由jdk提供,调用简单,不要需要导入jar包。而Quartz需要导入jar包,不是jdk自带。
2、Quartz的功能比Timer的功能强大完善。
3、Timer后台执行一个线程来完成定时任务,Quartz可以在后台执行多个线程来完成定时任务。
scheduleAtFixedRate方法
“fixed-rate”;如果第一次执行时间被delay了,随后的执行时间按照上一次开始的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑
schedule与scheduleAtFixedRate的区别
从两种情况看区别
1、首次计划执行的时间早于当前的时间(比如:当前时间是双十一的00:00:06而我们计划执行的时间是双十一的00:00:00)
2、任务执行所需的时间超出任务的执行周期间隔(比如:这个任务需要每隔两秒执行一次,但是单次这个任务的执行时间就是3秒)
Timer的定义
有且仅有一个后台线程 对 多个业务线程 进行 定时定频率 的调度
首先我们先明确一下什么是定时任务调度?
基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务。
Java中定时任务调动工具有俩:Timer 、Quartz
区别:
出身不同:Timer由jdk直接提供,不需jar包支持;Quartz需引入jar包。
能力不同:Timer简单定时任务;Quartz时间控制功能更强大。
底层机制:Timer只有一个后台线程执行;Quartz是多线程执行任务。
让我们看下官方文档api(JDK1.8)
可能有的小伙伴英语水平不太好,那让我们看下中文版吧:
那么我们可以归纳Timer的定义:有且仅有一个后台线程对多个业务线程进行定时定频率的调度
主要构件:
Timer工具类详解:
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; } }
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); } }
控制台打印显示:
作用:在时间等于或超过time的时候执行且仅执行一次task
参数: task-所要安排的任务
time-首次执行任务的时间
period-执行一次task的时间间隔,单位是毫秒
参数: task-所要安排的任务
delay-执行任务前的延迟时间,单位是毫秒
作用: 等待delay毫秒后执行且仅执行一次task
参数: 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); } }
参数: task-所要安排的任务
time-首次执行任务的时间
period-执行一次task的时间间隔,单位是毫秒
作用: 时间等于或超过time时首次执行task,之后每隔period毫秒重复执行一次task(和schedule的第二种用法是一样的)
参数: 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二者的不同
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():
作用:返回此任务最近实际执行的已安排执行的时间
cancel():
作用:终止此计时器,丢弃所有当前已安排的任务
purge():
作用:从此计时器的任务队列中移除所要已取消的任务
返回值:从队列中移除的任务数
"fixed-delay"如果第一次执行时间被delay了,随后的执行时间按上一次实际执行完成的时间点进行计算
console:
"fixed-rate"如果第一次执行时间被delay了,随后的执行时间按上一次实际执行完成的时间点进行计算,并且为了赶上进度会多次执行任务,因此TimerTask中的执行体需要考虑同步
console:
下一次执行时间相对于上一次实际执行完成的时间点,因此执行时间会不断延后
console:
下一次执行时间相对于上一次开始的时间点,因此执行的时间不会延后,因此存在并发性
console:
Timer有且仅有一个线程去执行定时任务,如果存在多个定时任务,且任务时间过长,会导致执行效果与预期不符
console:
同样scheduleAtFixedRate也不能解决并发问题:
如果TimerTask抛出RuntimeException,Timer会停止所有任务的执行
1.对时效性要求较高的多任务并发作业
2.对复杂的任务的调度
如果想要满足以上功能,需用到Quartz
11111
任务执行时间超出执行周期间隔
任务执行时间超出执行周期间隔
public class ScheduleAtFixedRateTest {
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秒前的时间,若当前时间为2018-3-17 16:03:30,那么设置之后时间变成2018-3-17 16:03:24
calendar.add(Calendar.SECOND, -6);
Timer timer = new Timer();
//第一次执行时间为6秒前,之后每隔两秒执行一次
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//打印当前的计划执行时间
System.out.println("Scheduled exec time is: " + sf.format(scheduledExecutionTime()));
System.out.println("task is being executed!");
}
}, calendar.getTime(), 2000);
}
}
首次计划执行时间早于当前时间
首次计划执行时间早于当前时间
scheduleAtFixedRate:下次开始执行的时间以上次run方法开始时间为基准。
schedule:下次开始执行的时间以上次run方法完成时间为基准。
scheduleAtFixedRate:同样时间回到过去,但是开始执行多次到达正常时间,然后间隔时间输出。
schedule:时间回到过去,但是开始执行时以一次到达正常时间,然后间隔时间输出。
Timer 的缺陷:
1 并发操作时的缺陷,这是因为 Timer 的后台只有一个执行线程导致的。
2 当任务抛出异常时的缺陷。如果 TimeTask 抛出 RuntimeException,Timer 会停止所有任务的执行。
根据缺陷,我们可以得出 Timer 的使用禁区。
1 对时效性要求较高的多任务并发作业,虽然 Timer 支持多任务执行,但那都是串行执行的。
2 对复杂的任务的调度,因为在复杂的任务中可能会出现异常,而Timer 中一旦出现异常,则停止执行。
Timer定义:有且仅有一个一个后台线程对多个业务线程进行定时定频率的调度。
Timer 组件: Timer 主体类和 TimeTask 实现类。
Timer 中包含一个 Time Task 的队列 和 一个 TimeThread 后台线程。
1.管理并发任务的缺陷:
每次有且仅有一个线程去执行定时任务,如存在多任务会导致任务时间过长(串行)
2.当任务抛出异常时的缺陷:
当抛出RuntimeException(如果不捕捉异常),会停止所有任务
3.在以下情况禁止使用
对时效性要求较高的多任务并发作业
对复杂的任务的调度