1. Timer 类
public class Timer {
public Timer() {
this("Timer-" + serialNumber());
}
private final TimerThread thread = new TimerThread(queue);
public Timer(String name) {
thread.setName(name);
thread.start();
}
}
创建 Timer 类时启动了1个新的非守护线程(TimerThread)
这个新启动的线程并不是守护线程,而且一直在运行。
一直在运行的原因是新线程内部有一个死循环,TimerThread.mainLoop()方法
1.1 TimerThread 类
class TimerThread extends Thread {
boolean newTasksMayBeScheduled = true;
private void mainLoop() {
while (true) {
try {
TimerTask task;
boolean taskFired;
synchronized(queue) {
// Wait for queue to become non-empty
while (queue.isEmpty() && newTasksMayBeScheduled)
queue.wait();
if (queue.isEmpty())
break; // Queue is empty and will forever remain; die
// ...
if (!taskFired) // Task hasn't yet fired; wait
queue.wait(executionTime - currentTime);
}
if (taskFired) // Task fired; run it, holding no locks
task.run();
} catch(InterruptedException e) {
}
}
}
}
注意变量 newTasksMayBeScheduled
1.2 schedule(TimerTask, delay)
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
1.3 TimerTask 类
TimerTask 是 abstract class, 执行计划任务由其子类实现
public abstract class TimerTask implements Runnable {
public abstract void run();
}
2. 定时任务
@Test
public void timerSchedule() throws Exception {
log.info("开始时间:" + System.currentTimeMillis());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("任务执行:" + System.currentTimeMillis());
}
}, 1000);
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
}
打印结果:
15:41:38.062 [main] INFO juc.TimerDemo - 开始时间:1698738098059
15:41:39.070 [Timer-0] INFO juc.TimerDemo - 任务执行:1698738099070
Timer-0 线程执行任务后,还存在
3. 线程销毁
3.1 终止计时器
Timer.cancel() 方法的作用是终止此计时器,丢弃当前所有已安排的任务
public class Timer {
public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}
}
3.2 示例
@Test
public void timerCancel() throws Exception {
log.info("开始时间:" + System.currentTimeMillis());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("任务执行:" + System.currentTimeMillis());
}
}, 5000);
TimeUnit.SECONDS.sleep(10);
timer.cancel();
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
}
执行结果:
15:51:06.810 [main] INFO juc.TimerDemo - 开始时间:1698738666808
15:51:11.831 [Timer-0] INFO juc.TimerDemo - 任务执行:1698738671831
查看 Timer-0 线程被销毁
4. 执行多个TimerTask任务
@Test
public void timerTasks() throws Exception {
log.info("开始时间:" + System.currentTimeMillis());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("任务执行:" + System.currentTimeMillis());
}
}, 1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("任务执行:" + System.currentTimeMillis());
}
}, 2000);
TimeUnit.SECONDS.sleep(5);
}
执行结果:
17:49:00.393 [main] INFO juc.TimerDemo - 开始时间:1698745740388
17:49:01.412 [Timer-0] INFO juc.TimerDemo - 任务执行:1698745741412
17:49:02.402 [Timer-0] INFO juc.TimerDemo - 任务执行:1698745742401
5. 延时执行TimerTask
TimerTask 是以队列的方式一个一个被顺序执行的,需等到前一个任务执行完成后才开始下一个任务
原因是创建了1个Timer类导致创建了1个TimerThread线程,1个TimerThread线程管理1个队列,在队列中得按顺序运行任务
@Test
public void delayTimerTask() throws Exception {
log.info("开始时间:" + System.currentTimeMillis());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@SneakyThrows
@Override
public void run() {
TimeUnit.SECONDS.sleep(5);
log.info("任务执行:" + System.currentTimeMillis());
}
}, 1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
log.info("任务执行:" + System.currentTimeMillis());
}
}, 2000);
TimeUnit.SECONDS.sleep(10);
}
打印结果:
17:54:07.700 [main] INFO juc.TimerDemo - 开始时间:1698746047698
17:54:13.727 [Timer-0] INFO juc.TimerDemo - 任务执行:1698746053727
17:54:13.728 [Timer-0] INFO juc.TimerDemo - 任务执行:1698746053728