一 time和timertask的关系
1.1 timer和timertask关系
1.Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个类;
2.Timer和TimerTask成对出现,Timer是定时器,TimerTask是定时任务。换句话说,定时任务TimerTask是给定时器Timer执行的具体任务。TimerTask实现Runnable接口的run方法。
Java的定时器Timer和定时任务TimerTask应用以及原理简析_java timertask-CSDN博客
3.每一个Timer仅对应唯一一个线程。Timer不保证任务执行的十分精确。
Timer类的线程安全的。
4.一个Timer可以调度任意多个TimerTask,所有任务都存储在一个队列中顺序执行,如果需要多个TimerTask并发执行,则需要创建两个多个Timer。
一个Timer可以执行多个TimerTask,但一个TimerTask只能被一个Timer使用(这和schedule中校验TimerTask的状态有关,TimerTask的生命周期(由不同的状态确定))。
简单的说Timer中有两个核心部分:
TimerThread是时间线程,控制TaskQueue中TimerTask的执行;
TaskQueue是一个工具类,管理TimerTask数组
1.2 timer的api
1.无参构造方法,简单通过Tiemer为前缀构造一个线程名称
2.有参构造方法,传入了是否为后台线程,后台线程当且仅当进程结束时,自动注销掉。
1.3 终止Timer线程
默认情况下,创建的timer线程会一直执行,主要有下面四种方式来终止timer线程:
1) 调用Timer.cancle()方法。可以在程序任何地方调用,甚至在TimerTask中的run方法中调用;
2) 创建Timer时定义位daemon守护线程,使用new Timer(true)语句;
3) 设置Timer对象为null,其会自动终止;????有待考证
4) 调用System.exit方法,整个程序终止。
1.4 timer注意事项
1) Timer线程不会捕获异常,所以TimerTask抛出的未检查的异常会终止timer线程。如果Timer线程中存在多个计划任务,其中一个计划任务抛出未检查的异常,则会引起整个Timer线程结束,从而导致其他计划任务无法得到继续执行。
2) Timer线程时基于绝对时间(如:2023/02/14 16:06:00),因此计划任务对系统的时间的改变是敏感的。
3) Timer是单线程,如果某个任务很耗时,可能会影响其他计划任务的执行。
因此,JDK1.5以上建议使用ScheduledThreadPoolExecutor来代替Timer执行计划任务。
二 操作案例
2.1 一个Timer执行多个Task,堵塞现象
package com.ljf.lockdemo.task.timerdemo;
import java.util.Timer;
import java.util.TimerTask;
/**
* @ClassName: TestDemo2
* @Description: TODO
* @Author: admin
* @Date: 2024/03/02 11:30:06
* @Version: V1.0
**/
public class TestDemo2 {
public static void main(String[] args) {
TimerTask task1=new TimerTask() {
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println("[当前线程是:"+name+",执行定时任务1:"+System.currentTimeMillis()+"]");
}
};
TimerTask task2=new TimerTask() {
@Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String name = Thread.currentThread().getName();
System.out.println("[当前线程是:"+name+",执行定时任务2:"+System.currentTimeMillis()+"]");
}
};
Timer timer=new Timer();
timer.schedule(task2,10000);
timer.schedule(task1,100,3000);
}
}
结果:
2.2 异常现象
1.现象操作,在timetask2中,模拟一个除以0的算术异常。
强调:在执行任何一个任务的run方法时,一旦run抛出了异常,Timer线程就会退出,从而所有定时任务都会被取消。如果希望各个定时任务互不干扰,一定要在run方法内捕获所有异常。
这里catch的异常为:integerrupteException
改成Exception e 如图
3.启动两个timer
2.3 总结
1个timer没有cancel掉,使用的一直是一个线程id;1个timer关闭后,再每次new后,使用的线程id都不相同。
2.在1个timer中,开启两个timetask;这个两个timertask串行执行,单线程;使用的线程id是相同的。