博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java定时器之Timer学习一
阅读量:6674 次
发布时间:2019-06-25

本文共 6500 字,大约阅读时间需要 21 分钟。

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 安排为一次执行或重复执行的任务。

/* TimerTask 的类定义,为抽象类,并且实现了 Runnable    可以通过继承该类,来实现自己的定时任务。*/public abstract class TimerTask implements Runnable

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

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

  • boolean 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:重复执行的时间间隔

/* 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):安排指定的任务在指定的时间开始进行重复的固定速率执行。
  • scheduleAtFixedRate(TimerTask task, long delay, 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:22Current exec name is:No.1current exec time is:2018-06-05 14:35:23Current exec name is:No.1current exec time is:2018-06-05 14:35:24Current exec name is:No.1

schedule() 的用法

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

在时间等于或者超过 time 的时候执行,且执行一次

/* 获取当前时间,并设置成距离当前时间3秒之后的时间 * 比如当前时间为: 2018-06-05 23:59:58 * 则设置之后的时间为: 2018-06-06 00:00:00 */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()));calendar.add(Calendar.SECOND, 3);/* 在时间等于或者超过 time 的时候执行,且执行一次 */myTimerTask.setName("schedule1");timer.schedule(myTimerTask, calendar.getTime());

输出的结果为:

current exec time is:2018-06-05 15:46:16current exec time is:2018-06-05 15:46:19Current exec name is:schedule1

时间等于或超过 time 的时候首次执行,之后每隔 period 毫秒重复执行一次 task

/* 获取当前时间,并设置成距离当前时间3秒之后的时间 * 比如当前时间为: 2018-06-05 23:59:58 * 则设置之后的时间为: 2018-06-06 00:00:00 */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()));calendar.add(Calendar.SECOND, 3);/** * 时间等于或超过 time 的时候首次执行,之后每隔 period 毫秒重复执行一次 task */myTimerTask.setName("schedule2");timer.schedule(myTimerTask, calendar.getTime(), 3000L);

输出的结果为:

current exec time is:2018-06-05 15:54:32current exec time is:2018-06-05 15:54:35Current exec name is:schedule2current exec time is:2018-06-05 15:54:38Current exec name is:schedule2current exec time is:2018-06-05 15:54:41Current exec name is:schedule2

等待 delay 毫秒之后执行且执行一次 task

/** * 等待 delay 毫秒之后执行且执行一次 task */myTimerTask.setName("schedule3");timer.schedule(myTimerTask, 1000);

输出结果为:

current exec time is:2018-06-05 16:00:06current exec time is:2018-06-05 16:00:07Current exec name is:schedule3

等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task

/** * 等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task */myTimerTask.setName("schedule4");timer.schedule(myTimerTask, 1000, 3000);

输出结果为:

current exec time is:2018-06-05 16:01:36current exec time is:2018-06-05 16:01:37Current exec name is:schedule4current exec time is:2018-06-05 16:01:40Current exec name is:schedule4current exec time is:2018-06-05 16:01:43Current exec name is:schedule4

scheduleAtFixedRate() 的用法

时间等于或者超过 time 时首次执行 task,之后每隔 period 毫秒重复执行一次

/* 获取当前时间,并设置成距离当前时间3秒之后的时间 * 比如当前时间为: 2018-06-05 23:59:58 * 则设置之后的时间为: 2018-06-06 00:00:00 */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()));calendar.add(Calendar.SECOND, 3);/* 时间等于或者超过 time 时首次执行 task,之后每隔 period 毫秒重复执行一次 */myTimerTask.setName("scheduleAtFixedRate1");timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 3000);

输出的结果为:

current exec time is:2018-06-05 16:11:48current exec time is:2018-06-05 16:11:51Current exec name is:scheduleAtFixedRate1current exec time is:2018-06-05 16:11:54Current exec name is:scheduleAtFixedRate1current exec time is:2018-06-05 16:11:57Current exec name is:scheduleAtFixedRate1

等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task

/* 等待 delay 毫秒之后,首次执行,并且之后每隔 period 毫秒重复执行一次 task */myTimerTask.setName("scheduleAtFixedRate2");timer.scheduleAtFixedRate(myTimerTask, 1000, 3000);

输出的结果为:

current exec time is:2018-06-05 16:15:47current exec time is:2018-06-05 16:15:48Current exec name is:scheduleAtFixedRate2current exec time is:2018-06-05 16:15:51Current exec name is:scheduleAtFixedRate2current exec time is:2018-06-05 16:15:54Current exec name is:scheduleAtFixedRate2

转载地址:http://hmgxo.baihongyu.com/

你可能感兴趣的文章
hibernate 一级缓存和二级缓存
查看>>
javac不是内部或外部命令
查看>>
mvc SelectList selected失效的解决方法
查看>>
JAVA 设计模式 中介者模式
查看>>
我的软件工程课目标
查看>>
var a={n:1}; var b=a; a.x=a={n:2}; console.log(a.x); console.log(b.x);
查看>>
【HDOJ】3016 Man Down
查看>>
window.open打开新页面,并将本页数据用过url传递到打开的页面;需要两个页面;...
查看>>
查看本机IP分为两种情况:
查看>>
Scala进阶之路-Scala特征类与unapply反向抽取
查看>>
洛谷P3057 [USACO12NOV]远处的牧场Distant Pastures
查看>>
hdu3415 Max Sum of Max-K-sub-sequence 单调队列
查看>>
6421B Lab2 DHCP的配置及故障排除
查看>>
[C# 基础知识梳理系列]专题一:深入解析委托——C#中为什么要引入委托
查看>>
FOSCommentBundle功能包:其它添加评论到页面的方法
查看>>
SQL Server 2012笔记分享-17:理解并设置文件表(FileTable)
查看>>
MongoDB运行状态、性能监控与分析
查看>>
Exchange 2016共享邮箱不保存已发送邮件的问题
查看>>
[C#基础知识系列]全面解析C#中静态与非静态
查看>>
SQL Server 2012笔记分享-40:自动维护索引
查看>>