一、定义:(祥见JDK文档)有且仅有一个后台线程对多个业务线程进行定时定频率的调度。
二、构件:Timer定时调用,TimerTask任务。
三、timer的schedule函数的四种用法:
1.schdule(task,time)
task:所要安排的任务。
time:执行任务的时间。
作用:在时间等于或者超过time的时候执行且仅执行一次task(当time晚于当前时间,后台线程等待,当time早于当前时间,启动后立即执行)。
2.schdule(task,time,period)
task:所要安排的任务。
time:执行任务的时间。
period:执行一次任务的时间间隔,单位是毫秒。
3.schdule(task,delay)
task:所要安排的任务。
time:执行任务前的延迟时间,单位毫秒。
作用:等待delay毫秒后执行且仅执行一次task。
4.schdule(task,delay,period)
task:所要安排的任务。
delay:执行任务前的延迟时间,单位毫秒。
period:执行一次任务的时间间隔,单位是毫秒。
5.schduleAtFixedRate(task,time,period)
task:所要安排的任务。
time:执行任务的时间。
period:执行一次任务的时间间隔,单位是毫秒。
6.schduleAtFixedRate(task,time,period)
task:所要安排的任务。
time:执行任务的时间。
period:执行一次任务的时间间隔,单位是毫秒。
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
public class MytimerTask extends TimerTask{
private String name;//任务名称
private AtomicInteger count = new AtomicInteger(0);//执行次数,线程安全
public MytimerTask(String name){
this.name = name;
}
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String time = format.format(calendar.getTime());
//已安排的任务最近执行时间
long nexttime = scheduledExecutionTime();
System.out.println(name+"最近执行时间时间:"+ format.format(nexttime));
//获取当前的值并自增
count.getAndIncrement();
System.out.println("执行"+count+"次"+name+"任务:"+ time);
if(count.get()>=5){
System.out.println("----"+name+"执行任务满五次取消任务----");
//取消当前timerTask里面的任务
cancel();
}
}
}
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class Mytimer{
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer();
TimerTask myTask1 = new MytimerTask("myTask1");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取当前时间
Calendar calendar = Calendar.getInstance();
System.out.println("启动定时器时间:"+dateFormat.format(calendar.getTime()));
//当前时间的三秒钟后
calendar.add(Calendar.SECOND, 3);
//在时间等于或超过time的时候执行且仅执行一次任务
timer.schedule(myTask1, calendar.getTime());
TimerTask myTask2 = new MytimerTask("myTask2");
Thread.sleep(5000);//休眠5s
//在时间等于或在超过time时,首次执行task,之后每隔period毫秒,重复执行一次task
timer.schedule(myTask2, calendar.getTime(), 3000);
TimerTask myTask3 = new MytimerTask("myTask3");
//等待delay毫秒后,执行且仅执行一次task
timer.schedule(myTask3, 2000);
//在等待delay毫秒后,首次执行task,之后每隔period毫秒,重复执行一次task
TimerTask myTask4 = new MytimerTask("myTask4");
timer.schedule(myTask4, 3000, 2000);
Thread.sleep(5000);//休眠5s
//在时间等于或在超过time时,首次执行task,之后每隔period毫秒,重复执行一次task
TimerTask myTask5 = new MytimerTask("myTask5");
timer.scheduleAtFixedRate(myTask5, calendar.getTime(), 2000);
//在延迟delay毫秒后,首次执行task,之后每隔period毫秒执行一次task
TimerTask myTask6 = new MytimerTask("myTask6");
timer.scheduleAtFixedRate(myTask6, 2000, 3000);
//从此计时器的任务队列中移除所有已取消的任务
timer.purge();
//丢弃当前所有已安排的任务
timer.cancel();
System.out.println("所有任务取消");
}
}
scheduleAtFixedRate与schedule的区别:
1.首次计划执行时间早于任务启动时间
schedule方法:如果第一次执行时间被延迟了,随后的执行时间按照上一次实际执行完成的时间点进行计算
scheduleAtFixedRate方法:如果第一次执行时间被延迟了,随后执行时间按照上一次开始时间点进行计算,并且为了赶上进度,会多次执行任务,因此TimerTask中的执行体需要考虑同步。
2.执行任务时间超出执行周期的间隔
schedule 方法:下一次执行时间相对于上一次实际完成的时间点,因此执行时间会不断延后
scheduleAtFixedRate方法:下一次执行时间相对于上一次开始的时间点,因此执行时间一般不会延后,因此存在并发性
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class Mytimer{
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//获取当前时间
Calendar calendar = Calendar.getInstance();
System.out.println("启动定时器时间:"+dateFormat.format(calendar.getTime()));
//当前时间的四秒钟之前
calendar.add(Calendar.SECOND, -4);
TimerTask myTask1 = new MytimerTask("myTask1");
timer.schedule(myTask1, calendar.getTime(), 2000);
TimerTask myTask2 = new MytimerTask("myTask2");
timer.scheduleAtFixedRate(myTask2, calendar.getTime(), 2000);
}
}
timer的缺陷:
1. 管理并发任务的缺陷: timer有且仅有一个后台线程去执行定时任务,如果存在多个任务,且任务时间过长会导致执行效果与预期不符。
2.当任务抛出异常时的缺陷:如果TimerTask抛出RuntimeException,timer会停止所有任务的运行
Timer的使用禁区:
1.对时效性要求较高的任务并发作业
2.对复杂任务的调度