文章目录

  • 1 概览
  • 2 终止Timer线程
  • 3 反复执行一个任务
  • 4 进一步分析schedule和scheduleAtFixedRate
  • 5 一些注意的问题

1 概览

Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。
TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。
简单的一个例程:

import java.util.Timer;
import java.util.TimerTask;
/**
* Simple demo that uses java.util.
* Timer to schedule a task to execute
* once 5 seconds have passed.
*/
public class Reminder { Timer timer;   public Reminder(int seconds) {       timer = new Timer();       timer.schedule(new RemindTask(), seconds*1000);    }
class RemindTask extends TimerTask {        public void run() {            System.out.println("Time's up!");            timer.cancel(); //Terminate the timer thread       } }   public static void main(String args[]) {        System.out.println("About to schedule task.");        new Reminder(5);        System.out.println("Task scheduled.");    }}
运行结果:
About to schedule task.
5秒钟之后你会看到:
Time's up!

这个小例子可以说明一些用Timer线程实现和计划执行一个任务的基础步骤:
实现自定义的TimerTask的子类,run方法包含要执行的任务代码,在这个例子里,这个子类就是RemindTask
实例化Timer类,创建计时器后台线程。
实例化任务对象 (new RemindTask()),制定执行计划。
这里用schedule方法,第一个参数是TimerTask对象,第二个参数表示开始执行前的延时时间(单位是milliseconds,这里定义了5000)。
还有一种方法可以指定任务的执行时间,如下例,指定任务在11:01 p.m执行:

 //Get the Date corresponding to 11:01:00 pm today.Calendar calendar =Calendar.getInstance();calendar.set(Calendar.HOUR_OF_DAY,23);calendar.set(Calendar.MINUTE, 1);calendar.set(Calendar.SECOND, 0);Date time = calendar.getTime();timer = new Timer();timer.schedule(new RemindTask(), time);

2 终止Timer线程

默认情况下,只要一个程序的timer线程在运行,那么这个程序就会保持运行。当然,可以通过以下四种方法终止一个timer线程:

  • timer.cancle()方法
    调用timercancle方法。可以从程序的任何地方调用此方法,甚至在一个timer taskrun方法里
  • 成为daemon线程
    timer线程成为一个daemon线程(可以在创建timer时使用new Timer(true)达到这个目地),这样当程序只有daemon线程的时候,它就会自动终止运行。
  • 删除timer对象引用
    timer相关的所有task执行完毕以后,删除所有此timer对象的引用(置成null),这样timer线程也会终止
  • System.exit方法
    调用System.exit方法,使整个程序(所有线程)终止。

Reminder的例子使用了第一种方式。在这里不能使用第二种方式,因为这里需要程序保持运行直到timer的任务执行完成,如果设置成daemon,那么当main线程结束的时候,程序只剩下timer这个daemon线程,于是程序不会等timer线程执行task就终止了。

有些时候,程序的终止与否并不只与timer线程有关。举个例子,如果我们使用AWTbeep,那么AWT会自动创建一个非daemon线程来保持程序的运行。下面的代码我们对Reminder做了修改,加入了beeping功能,于是我们需要加入System.exit的调用来终止程序。

import java.util.Timer;
import java.util.TimerTask;
import java.awt.Toolkit;/**
* Simple demo that uses java.util.Timer to schedule a task to execute
* once 5 seconds have passed.
*/public class ReminderBeep {Toolkit toolkit;Timer timer;public ReminderBeep(int seconds) {toolkit = Toolkit.getDefaultToolkit();timer = new Timer();timer.schedule(new RemindTask(), seconds*1000);}class RemindTask extends TimerTask {public void run() {System.out.println("Time's up!");toolkit.beep();//timer.cancel(); //Not necessary because we call System.exitSystem.exit(0);   //Stops the AWT thread (and everything else)}}public static void main(String args[]) {System.out.println("About to schedule task.");new ReminderBeep(5);System.out.println("Task scheduled.");}
}

3 反复执行一个任务

先看一个例子:

public class AnnoyingBeep {Toolkit toolkit;Timer timer;public AnnoyingBeep() {toolkit = Toolkit.getDefaultToolkit();timer = new Timer();timer.schedule(new RemindTask(),0,        //initial delay1*1000);  //subsequent rate}class RemindTask extends TimerTask {int numWarningBeeps = 3;public void run() {if (numWarningBeeps > 0) {toolkit.beep();System.out.println("Beep!");numWarningBeeps--;} else {toolkit.beep();System.out.println("Time's up!");//timer.cancel(); //Not necessary because we call System.exitSystem.exit(0);   //Stops the AWT thread (and everything else)}}}...
}执行,你会看到如下输出:Task scheduled.
Beep!
Beep!      //one second after the first beep
Beep!      //one second after the second beep
Time's up! //one second after the third beep

这里使用了三个参数的schedule方法用来指定task每隔一秒执行一次。
如下所列为所有Timer类用来制定计划反复执行task的方法 :

schedule(TimerTask task, long delay, long period)
schedule(TimerTask task, Date time, long period)
scheduleAtFixedRate(TimerTask task, long delay, long period)
scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

当计划反复执行的任务时,如果注重任务执行的平滑度,那么请使用schedule方法,如果你在乎的是任务的执行频度那么使用 scheduleAtFixedRate方法。 例如,这里使用了schedule方法,这就意味着所有beep之间的时间间隔至少为1秒,也就是说,如果有一个beap因为某种原因迟到了(未按计划执行),那么余下的所有beep都要延时执行。如果想让这个程序正好在3秒以后终止,无论哪一个beep因为什么原因被延时,那么需要使用scheduleAtFixedRate方法,这样当第一个beep迟到时,那么后面的beep就会以最快的速度紧密执行(最大限度的压缩间隔时间)

4 进一步分析schedule和scheduleAtFixedRate

2个参数的schedule在制定任务计划时, 如果指定的计划执行时间scheduledExecutionTime<=systemCurrentTime,则task会被立即执行。scheduledExecutionTime不会因为某一个task的过度执行而改变。

3个参数的schedule在制定反复执行一个task的计划时,每一次执行这个task的计划执行时间随着前一次的实际执行时间而变,也就是scheduledExecutionTime(第n+1次)=realExecutionTime(第n次)+periodTime
也就是说如果第n次执行task时,由于某种原因这次执行时间过长,执行完后的systemCurrentTime>=scheduledExecutionTime(第n+1次),则此时不做时隔等待,立即执行第n+1task,而接下来的第n+2taskscheduledExecutionTime(第n+2次)就随着变成了realExecutionTime(第n+1次)+periodTime。说白了,这个方法更注重保持间隔时间的稳定。

3个参数的scheduleAtFixedRate在制定反复执行一个task的计划时,每一次执行这个task的计划执行时间在最初就被定下来了,也就是 scheduledExecutionTime(第n次)=firstExecuteTime+n*periodTime;如果第n次执行task时,由 于某种原因这次执行时间过长,执行完后的systemCurrentTime>=scheduledExecutionTime(第n+1次),则 此时不做period间隔等待,立即执行第n+1task,而接下来的第n+2次的taskscheduledExecutionTime(第n+2次)依然还是firstExecuteTime+(n+2)*periodTime这在第一次执行task就定下来了。说白了,这个方法更注重保持执行频率的稳定。

5 一些注意的问题

每一个Timer仅对应唯一一个线程
Timer不保证任务执行的十分精确
Timer类的线程安全的

java之定时器Timer相关推荐

  1. Java的定时器Timer和定时任务TimerTask应用以及原理简析

    记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析.在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.u ...

  2. java捕获定时器抛出的异常_详细了解Java中定时器Timer的使用及缺陷分析

    在需要定时并且周期执行任务时,在最初的JAVA工具类库中,Timer可以实现任务的定时周期执行的需求,不过有一定的缺陷,比如,Timer是基于绝对时间而非相对时间,因此Timer对系统时钟比较敏感,本 ...

  3. java之定时器任务Timer用法

    在项目开发中,经常会遇到需要实现一些定时操作的任务,写过很多遍了,然而每次写的时候,总是会对一些细节有所遗忘,后来想想可能是没有总结的缘故,所以今天小编就打算总结一下可能会被遗忘的小点: 1. pub ...

  4. Java定时器Timer

    Java定时器Timer 在JDK库中,Timer类主要负责计划任务的功能,也就是在指定的时开始执行某一个任务.Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类,执行计划 ...

  5. Java定时器Timer学习之一

    2019独角兽企业重金招聘Python工程师标准>>> 种类: 接通延时型定时器:接通延时型定时器是各种PLC(可编程控制器)中最常见最基本的定时器,这种定时器在Siemens的PL ...

  6. java定时器阻塞主线程_Java基础_死锁、线程组、定时器Timer

    一.死锁问题: 死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 比如,线程一需要第一把所,此时锁处于空闲状态,给了 ...

  7. Java定时器Timer和第三方定时器Quartz

    概述 定时器在应用广泛,比如定时统计数据生成报表.每隔设定的时间提醒用户等.Java.util包自带的定时器Timer提供简单的定点执行功能,而Quartz是一个第三方提供的定时器框架. 对比 Tim ...

  8. java定时器关闭再重启_Android定时器Timer的停止和重启实现代码

    本文介绍了Android定时器Timer的停止和重启实现代码,分享给大家,具体如下: 7月份做了一个项目,利用自定义控件呈现一幅动画,当时使用定时器来控制时间,但是当停止开启时总是出现问题.一直在寻找 ...

  9. java定时器timer_Java定时器Timer

    Java定时器Timer 在JDK库中,Timer类主要负责计划任务的功能,也就是在指定的时开始执行某一个任务.Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类,执行计划 ...

最新文章

  1. 华为js面试题_四面腾讯与华为,大厂前端面试真BT!
  2. cmder默认的命令提示符λ改成$
  3. ThinkPHP导入第三方类库Vendor
  4. 01 MySQL锁概述
  5. 2021-05-25 传递函数阶跃响应指标的matlab计算
  6. JVM调优系列:(二)JVM运行时数据区域
  7. dtree 无法出现横向滚动条 (clip)
  8. (转载)用oracle触发器对记录表增加记录的问题
  9. 由于不能随便改路径,所以写在这里
  10. Dynamipsgui入门教程
  11. Windows互斥锁的使用
  12. 为什么每个邮件收到后都会有一个htm的附件_Python3.x 发送各种形式的告警邮件内容...
  13. Java 递归算法解决“八皇后问题”
  14. win2012服务器 注册表,第十一章 Windows Server 2012 R2 注册表域注册表编辑器 ---学习笔记...
  15. 『前端面试资料』 前端面试考题汇总 摘自校内某内推群群公告
  16. 用SDK包开发K66FX18学习笔记(4)
  17. 第二十三章 Unity 材质
  18. c语言less函数,Less 函数
  19. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!...
  20. python复利计算_python复利代码

热门文章

  1. acrobat 弹窗不停怎么办?
  2. namenode的ha配置,亲测
  3. 收集了一些图片素材网站
  4. 哈佛大学公开课:计算机科学cs50 学习笔记(第7集:数组,其它)
  5. 将hyperf后台运行并热重启
  6. 【硬件】关于显示器自动弹出显示菜单的解决方案
  7. 由于没有远程桌面授权服务器可以提供许可证,远程会话连接已断开。请跟服务器管理员联系
  8. 驾校管理软件之军博软件
  9. 使用KNN算法对水果进行分类
  10. 惨遭全国大厂封杀的百分百进大厂的面试题,确定不来看看。