1. Timer 和 TimerTask
- Timer:设置计划任务
- TimerTask:任务的实现
2. schedule(TimerTask task, Date time) 方法
指定日期执行一次定时任务
2.1 晚于当前时间执行任务
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer();
timer.schedule(getTimerTask(), planDate);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task run date=" + new Date());
}
};
}
}
2.2 早于当前时间执行任务,则立即执行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 10);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("task planDate=" + planDate);
Timer timer = new Timer();
timer.schedule(getTimerTask(), planDate);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task run date=" + new Date());
}
};
}
}
2.3 多个任务执行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date planDate1 = calendar.getTime();
calendar.add(Calendar.SECOND, 5);
Date planDate2 = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("task1 planDate1=" + planDate1);
System.out.println("task2 planDate2=" + planDate2);
Timer timer = new Timer();
timer.schedule(getTimerTask1(), planDate1);
timer.schedule(getTimerTask2(), planDate2);
System.out.println("main end");
}
private static TimerTask getTimerTask1() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task1 run date=" + new Date());
}
};
}
private static TimerTask getTimerTask2() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task2 run date=" + new Date());
}
};
}
}
2.4 多个任务时的延迟执行
TimerTask 任务是以队列的方式一个一个被顺序执行的,所以任务实际执行的时间可能和计划的不一致,因为前面的任务可能执行的时间过长,导致后面的任务的执行被延迟了
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date planDate1 = calendar.getTime();
calendar.add(Calendar.SECOND, 5);
Date planDate2 = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("task1 planDate1=" + planDate1);
System.out.println("task2 planDate2=" + planDate2);
Timer timer = new Timer();
timer.schedule(getTimerTask1(), planDate1);
timer.schedule(getTimerTask2(), planDate2);
System.out.println("main end");
}
private static TimerTask getTimerTask1() {
return new TimerTask() {
@Override
public void run() {
try {
System.out.println("task1 run begin date=" + new Date());
Thread.sleep(20000);
System.out.println("task1 run end date=" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
private static TimerTask getTimerTask2() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task2 run begin date=" + new Date());
System.out.println("task2 run end date=" + new Date());
}
};
}
}
2.5 进程未销毁?
-
可以发现,上面的自动任务执行完后进程未销毁,因为创建一个 Timer 就是启动一个新的线程,这个线程默认情况下不是守护线程,所以它一直在运行
-
Timer 可以设置以守护线程的方式运行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer(true);
timer.schedule(getTimerTask(), planDate);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task run Date=" + new Date());
}
};
}
}
上面的代码执行后,打印了"main end"后进程销毁了,未执行 TimerTask 任务。因为 main 主线程执行完毕后销毁了,Timer 作为守护线程也跟着一起销毁了
3. schedule(TimerTask task, Date firstTime, long period) 方法
指定日期后,再按指定间隔时间(period)周期性无限循环执行任务
3.1 晚于当前时间执行任务
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 5);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer();
timer.schedule(getTimerTask(), planDate, 3000);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task run date=" + new Date());
}
};
}
}
3.2 早于当前时间执行任务,则立即执行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 10);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer();
timer.schedule(getTimerTask(), planDate, 3000);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
System.out.println("task run date=" + new Date());
}
};
}
}
3.3 延迟执行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 5);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer();
timer.schedule(getTimerTask(), planDate, 3000);
System.out.println("main end");
}
private static TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
try {
System.out.println("task run begin date=" + new Date());
Thread.sleep(4000);
System.out.println("task run end date=" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
}
4. cancel() 方法
4.1 TimerTask 类的 cancel() 方法
TimerTask 类的 cancel() 方法是将自身从任务列表中清除
public class Test {
public static void main(String[] args) {
Date currentDate = new Date();
System.out.println("currentDate=" + currentDate);
Timer timer = new Timer();
timer.schedule(new TimerTaskA(), currentDate, 2000);
timer.schedule(new TimerTaskB(), currentDate, 3000);
System.out.println("main end");
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run date=" + new Date());
this.cancel();
}
}
static class TimerTaskB extends TimerTask {
@Override
public void run() {
System.out.println("taskB run date=" + new Date());
}
}
}
4.2 Timer 类的 cancel() 方法
Timer 类的 cancel() 方法是将任务队列中所有任务清除
public class Test {
public static void main(String[] args) throws InterruptedException {
Date currentDate = new Date();
System.out.println("currentDate=" + currentDate);
Timer timer = new Timer();
timer.schedule(new TimerTaskA(), currentDate, 2000);
timer.schedule(new TimerTaskB(), currentDate, 3000);
Thread.sleep(10000);
timer.cancel();
System.out.println("main end");
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run date=" + new Date());
}
}
static class TimerTaskB extends TimerTask {
@Override
public void run() {
System.out.println("taskB run date=" + new Date());
}
}
}
4.3 Timer 类的 cancel() 方法注意事项
Timer 类的 cancel() 方法有时并不一定会停止执行任务,因为 Timer 类的 cancel() 方法有时没有争抢到 queue 锁
public class Test {
private static int i = 1;
public static void main(String[] args) {
while (true) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 3);
Timer timer = new Timer();
timer.schedule(new TimerTaskA(), calendar.getTime());
timer.cancel();
i++;
}
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run i=" + i);
this.cancel();
}
}
}
5. schedule(TimerTask task, long delay) 方法
以执行该方法时的时间为参考时间,在此基础上延迟指定毫秒数(delay)后执行一次 TimerTask 任务
public class Test {
public static void main(String[] args) {
System.out.println("currentTime=" + new Date());
Timer timer = new Timer();
timer.schedule(new TimerTaskA(), 2000);
System.out.println("main end");
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run date=" + new Date());
}
}
}
6. schedule(TimerTask task, long delay, long period) 方法
以执行该方法时的时间为参考时间,在此基础上延迟指定毫秒数(delay)后,再以间隔时间(period)周期性无限循环执行任务
public class Test {
public static void main(String[] args) {
System.out.println("currentTime=" + new Date());
Timer timer = new Timer();
timer.schedule(new TimerTaskA(), 2000, 5000);
System.out.println("main end");
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run date=" + new Date());
}
}
}
7. scheduleAtFixedRate() 方法的追赶性
scheduleAtFixedRate() 方法具有追赶性。如果是早于当前时间执行任务的情况下,调用该方法会将这段提前时间段内对应的任务”补充“地执行
public class Test {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 20);
Date planDate = calendar.getTime();
System.out.println("currentDate=" + new Date());
System.out.println("planDate=" + planDate);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTaskA(), planDate, 2000);
System.out.println("main end");
}
static class TimerTaskA extends TimerTask {
@Override
public void run() {
System.out.println("taskA run date=" + new Date());
}
}
}
学自《Java多线程编程核心技术》