Timer定时器学习笔记

299 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。​​​​​​​​​​​​​​​ ​

什么是定时任务调度?

基于给定的时间点、给定的时间间隔或给定的执行次数自动执行的任务。

在java中的定时调度工具:Timer,Quartz。实际中的大多数的定时任务都可以由Timer实现,但是和Quartz相比功能还是稍弱一点。

Timer和Quartz的区别:

1.出身不同:

Timer是由jdk提供,调用方式简单粗暴,不需要别的jar的支持。

Quartz是源于OpenSynmphony提供的强大的开源任务调度框架,并非jdk自带。需要引入jar。

2.能力区别:

主要体现在对时间的控制上。Quartz对时间的控制功能远比Timer强大。

3.底层功能:

Timer只需要一个后台线程去完成定时任务。Quartz后台拥有一个线程池去执行定时任务,可以有多个线程去执行任务。

Timer简介:

Timer是java.util包下的一个类。有且仅有一个后台线程对多个业务线程进行定时定频率的调度。Timer可以理解为是一个后台执行的线程,TimerTask是业务线程,通过Timer定时调用TimerTask来实现对业务的定时调用。

Timer类由四部分组成:

Timer是主类,包含两个属性,一个是thread,即后台线程。另一个事队列,队列里面是TimerTask,TimerTask中的run方法里定义了要定时执行的业务逻辑。后台线程Thread定时定频率地执行队列中的TimerTask中的run方法来实现定时任务调度。

TimerTask的cancel():取消当前TimerTask里的任务。

scheduleExecutionTime():返回此任务最近实际执行的已安排执行的时间。(也就是离现在最近一次安排的任务的执行时间)

Timer的cancel():终止此计时器,丢弃所有当前已安排的任务。

purge():从此计时器的任务队列中移除所有已取消的任务。返回值是从队列中移除的任务数。

Schedule()与scheduleAtFixedRate()都是表示调度任务的方法,他们的区别是:

场景一:首次计划执行时间早于当前时间(如当前时间是00:06,首次计划执行时间是00:00)

schedule():第一次应当执行的时间已经过去了,那就从当前时间开始第一次执行,后面的执行时间按照第一次实际执行完成的时间点进行计算。

scheduledAtFixedRate():如果第一次执行时间被delay了,随后的执行时间按照上一次开始的时间点进行计算,因此执行时间不会延后,但是存在任务并发的问题。

场景二:任务执行时间超出执行周期间隔(如任务执行完成需要3秒钟,而执行周期是2秒钟)

schedule():下一次执行时间相对于上一次实际执行完成的时间点,因此执行时间会不断延后。比如说,任务真实完成时间是00:03,任务执行周期是2分钟,那么下一次执行时机是上一次任务执行完成的时间,也就是00:03。

scheduledAtFixedRate():下一次执行时间相对于上一次开始的时间点(要加上执行周期),因此执行时间一般不会延后,但存在并发性。

Timer的缺陷:

1.管理并发任务的缺陷:Timer有且仅有一个线程去执行定时任务,如果存在多个任务,且任务时间过长,会导致执行效果与预期不符。

2.当任务抛出异常时的缺陷:对RuntimeException的支持力度不够。如果TimerTask抛出RuntimeException,Timer会停止所有任务的运行。

Timer使用的禁区:

1.对时效性要求较高的多任务并发作业。(因为不支持并发)

2.对复杂的任务的调度。(因为复杂任务容易抛出异常,导致所有任务停止运行)

代码实现:

Timer线程:

package com.wyh;

import java.text.SimpleDateFormat;
import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		
		//Timer实例
		Timer timer = new Timer();
		//MyTimerTask实例
		MyTimerTask myTimerTask = new MyTimerTask();
		//打印当前时间
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println(sf.format(System.currentTimeMillis()));
		//timer定时定频率调用myTimerTask的业务逻辑
		//即第一次执行是在当前时间三秒之后,之后每隔一秒执行一次
		timer.schedule(myTimerTask, 3000L, 1000L);

	}

}

TimerTask:

package com.wyh;

import java.text.SimpleDateFormat;
import java.util.TimerTask;

public class MyTimerTask extends TimerTask {

	@Override
	public void run() {
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("执行任务啦"+sf.format(System.currentTimeMillis()));

	}

}

此处调度的任务是打印输出。运行MyTimer进行测试:

简单的Timer定时任务就实现了。