种类:

  1. 接通延时型定时器:接通延时型定时器是各种PLC(可编程控制器)中最常见最基本的定时器,这种定时器在Siemens的PLC中,成为SD型定时器
  2. 断开延时型定时器:这种定时器是当输入条件00000为ON时无延时作用,只有在输入条件00000为OFF时产生延时作用.在siemens的PLC中,称为SF型定时器
  3. 保持型接通延时定时器:这种定时器是当输入条件00000为ON后,即产生锁存功能,即使输入条件00000又变为OFF,仍视输入条件位ON,当定时器的当前值等于设定值时,定时器动作,这种定时器在Simens的PLC中,称为SS型定时器
  4. 脉冲型定时器:这种定时器是当输入条件00000为ON后,定时器即时动作,但经过定时器所设定的时间后,即使输入条件00000仍未ON,定时器却变为OFF状态.即这种定时器ON状态的维持时间是由设定值决定的.如果00000为ON的时续时间小于定时器的设定值,定时器的ON状态维持时间为输入田间00000为ON的持续时间.这种定时器在Siemens的PLC中,称为SP型定时器
  5. 扩张型脉冲定时器:这种定时器与脉冲型定时器的区别是,最后要输入条件00000出现了ON状态,不管其持续时间多长,均可使定时器为ON的维持的时间与定时器的设定值一致.这种定时器在Siemens的PLC中,称为SE型定时器

在Java中会存在每隔一定时间去执行某个任务的现象,如:每天定时清理服务器上的日志文件,每天定时上传文件或下载文件等。在Java中要实现定时任务,需要使用Timer类

Timer的定义:

有且仅有一个后台线程对多个业务进行定时定频的调度。Timer类可以保证多个线程可以共享单个Timer对象而无需进行外部同步,所以Timer类是线程安全的

核心的两个类:

  • java.util.Timer和java.util.TimerTask
  • java.util.Timer。实际上是个线程,定时调度所拥有的TimerTasks
  • 一个TimerTask实际上就是一个拥有run()方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。
  • TimerTask类是一个定时任务类,该类实现了Runnable接口,而且是一个抽象类

说明

java.util.TimerTask

TimerTask是一个抽象类,由Timer安排为一次执行或重复执行的任务。

public abstract class TimerTask implements Runnable 它有一个抽象方法run()方法,该方法用于执行相应计时器任务要执行的操作。因此每一个具体的任务类都必须继承TimerTask,然后重写run()方法。

另外它还有两个非抽象的方法:

  • boolen cancel(): 取消此计时器任务
  • long scheduledExecutionTime(): 返回此任务最近实际执行的安排执行时间。

java.util.Timer

注意:javax.swing包中也有一个Timer类,如果import中用到swing包,要注意名字的冲突。

Timer定时器实例有多种构造方法;

  • Timer():创建一个新定时器
  • Timer(boolean isDaemon):创建一个新定时器,可以指定其相关的线程作为守护程序运行。
  • Timer(String name):创建一个新定时器,其相关的线程具有指定的名称
  • Timer(String name,boolean isDaemon):创建一个新计时器,其相关的线程具有指定的名称,并且可以指定作为守护程序运行

Timer定时器的schedule()(调度方法)

下面例子部分参数说明:

delay:延迟执行的毫秒数,即在delay毫秒之后第一次执行

period:重复执行的时间间隔

Timer类有四种使用方法:

/* time为Date类型:在指定时间执行一次。 */
timer.schedule(task, time); 

/* firstTime为Date类型,period为long 
 从firstTime时刻开始,每隔period毫秒执行一次。 */
timer.schedule(task, firstTime, period); 

/* delay 为 long类型:从现在起过delay毫秒执行一次 */
timer.schedule(task, delay) 

/* delay 为 long, period 为 long:从现在起过delay毫秒以后,每隔 period  毫秒执行一次。*/
timer.schedule(task, delay, period)

**方法名称schedule()和scheduleAtFixedRate()的区别: **

  • schedule()方法跟注重保持间隔时间的稳定:保障每隔period时间可调用一次
  • scheduleAtFixedRate()方法更注重保持执行频率的稳定:保障多次调用的频率趋近于period时间,如果任务执行时间大于period,会在任务执行之后马上执行下一次任务

scheduleAtFixedRate()

  • scheduleAtFixedRate(TimerTask task,Date firstTime,long period):安排指定的任务在指定的时间开始进行重复的固定速率执行。

实例代码说明:

MyTimerTask.java

作为一个需要调度的任务类。

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

public class MyTimerTask extends TimerTask {

	private String name;

	public MyTimerTask(String inputName) {
		name = inputName;
	}

	[@Override]()
	public void run() {

		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("current exec time is:"+ sf.format(calendar.getTime()));

		// 重写来自于 TimerTask 的 run()
		System.out.println("Current exec name is:" + name);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

MyTimer.java

测试调度 MyTimerTask

import java.util.Timer;

public class MyTimer {

	public static void main(String[] args) {
		// 创建一个 timer 实例
		Timer timer = new Timer();

		// 创建一个 MyTimerTask 实例
		MyTimerTask myTimerTask = new MyTimerTask("No.1");

		/* 通过 timer 定时定频调用 myTimerTask的业务逻辑
		 * 即第一次执行是在当前时间的两秒之后,之后每隔一秒执行一次
		 */
		timer.schedule(myTimerTask, 2000L, 1000L);
	}

}

输入结果:

  • current exec time is:2018-06-05 14:35:22
  • Current exec name is:No.1
  • current exec time is:2018-06-05 14:35:23
  • Current exec name is:No.1
  • current exec time is:2018-06-05 14:35:24
  • Current exec name is:No.1

schedule()的用法

代码紧跟上面的例子来做。

  • purge()从定时器任务队列中移除所有已取消的任务
  • 应用实例: