【Java】Timer和TimerTask详解

article/2025/9/12 11:59:17
以下内容根据 The JavaTM Tutorial 和相关API doc翻译整理,以供日后参考:
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方法。你可以从程序的任何地方调用此方法,甚至在一个timer task的run方法里。
让timer线程成为一个daemon线程(可以在创建timer时使用new Timer(true)达到这个目地),这样当程序只有daemon线程的时候,它就会自动终止运行。 
当timer相关的所有task执行完毕以后,删除所有此timer对象的引用(置成null),这样timer线程也会终止。 
调用System.exit方法,使整个程序(所有线程)终止。 
Reminder 的例子使用了第一种方式。在这里不能使用第二种方式,因为这里需要程序保持运行直到timer的任务执行完成,如果设成daemon,那么当main线程 结束的时候,程序只剩下timer这个daemon线程,于是程序不会等timer线程执行task就终止了。

有些时候,程序的终止与否 并不只与timer线程有关。举个例子,如果我们使用AWT来beep,那么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.exit
    System.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 delay
               1*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.exit
                System.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


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



5.一些注意的问题
每一个Timer仅对应唯一一个线程。
Timer不保证任务执行的十分精确。
Timer类的线程安全的。

      原文地址 http://diger.cn/article.asp?id=191

http://chatgpt.dhexx.cn/article/wl4lkyKQ.shtml

相关文章

【Linux内核代码分析1】Linux时间子系统及HRTIMER实现

Linux时间子系统软件架构 &#xff08;1&#xff09;嵌入式设备需要较好的电源管理策略。传统的linux会有一个周期性的时钟&#xff0c;即便是系统无事可做的时候也要醒来&#xff0c;这样导致系统不断的从低功耗&#xff08;idle&#xff09;状态进入高功耗的状态。这样的设计…

Linux Time

1、Linux时钟框架 上图是linux时钟框架一个经典的描述。本质上linux各种时钟架构和服务是基于硬件提供的两种timer而构建的。 1、定时Timer 这类timer每个cpu都有一个独立的&#xff0c;称为local timer。这类timer的中断一般都是PPI&#xff08;Private Peripheral Interrup…

Linux时间子系统基础(三):时间的维护者:timekeeper

本系列文章的前两节讨论了用于计时的时钟源&#xff1a;clocksource&#xff0c;以及内核内部时间的一些表示方法&#xff0c;但是对于真实的用户来说&#xff0c;我们感知的是真实世界的真实时间&#xff0c;也就是所谓的墙上时间&#xff0c;clocksource只能提供一个按给定频…

攻防世界--TimeKeeper

将price和id加上引号&#xff0c;触发debug 联想到扫描目录出现的/console Flask debug pin安全问题 这种方法有点难&#xff0c;换种方法 目录穿越 可以成功读取任意文件&#xff0c;获得flag。

html 时间控件滚动选择器,TimePicker

TimePicker滚动的列表选择器&#xff0c;可用于时间选择。多个TimePicker组合起来可实现复杂的应用&#xff0c;如效果图中&#xff0c;俩个TimePicker组合&#xff0c;一个表示"分"、一个表示"秒"。 效果图&#xff1a; 如何使用xml创建 android:id"…

Linux时间子系统之时间维护层(Time Keeper)

时间维护层会收到Tick层的周期调用&#xff0c;每次调用的周期是由内核参数决定的。在此期间&#xff0c;时间维护层可以读取时钟源设备的周期数&#xff0c;从而感知时间的流逝。 目前时间维护层主要负责维护以下几种类型的时间&#xff1a; 实时时间&#xff08;CLOCK_REAL…

【Linux内核|时间子系统】Linux时间子系统(二)timekeeping简介

文章目录 1. timekeeping2. 计算墙上时间、启动时间差值3. timekeeper初始化3.1. 默认时钟源3.2. tk_setup_internals3.3. 设置时间 4. timekeeping_update4.1. tk_update_ktime_data&#xff1a;tkr_mono和tkr_raw设置4.2. update_fast_timekeeper4.3. shadow_timekeeper 1. t…

matlab 梯度下降 求偏导,通过计算图求梯度下降中各偏导的推导

通过计算图求梯度下降中各偏导的推导 Author: nex3z 2017-08-30 在 Neural Networks and Deep Learning 课程的 Logistic Regression Gradient Descent 一节以逻辑回归为例&#xff0c;介绍了使用计算图(Computation Graph)求梯度下降中各偏导的方法&#xff0c;但没有给出具体…

matlab|求导数/最值

本博文源于matlab求导数求极值求最值&#xff0c;涉及内容极限命令求导/diff求导/一元函数一阶导数&#xff0c;多阶导数&#xff0c;求参数导数/函数极值和最值/不给定区间求最值 用极限命令求导 例子&#xff1a;求函数3sinx4x^2在x0处的导数 >> syms t; limit((3*…

matlab 梯度下降 求偏导,吴恩达机器学习课程课时12梯度下降算法中参数θ0,θ1求偏导...

最近学习吴恩达的机器学习课程。 看到了线性回归的梯度下降算法。课程中将了一个非常简单的线性回归&#xff1a; 比如给出一些房子的size和对应的price&#xff0c;我们可以建立一个模型(在此模型就是线性回归)&#xff0c; 希望之后在给出任意一个房子的size&#xff0c;可以…

matlab求COPULA偏导,matlab note

Update date&#xff1a;2018-01-05 Matlab Note 1 vine-copula 1.1 xlsread() 打开xlsx里面的数据 S3CE xlsread(电表建模数据.xlsx,S3CE&#xff0c;‘G2:G52’) 1.2常见希腊发音总结 image.png 3.prob() 连乘 由于matlab中的元素是以矩阵为单位,prod(x)就是把x向量中所有元…

matlab求解多元函数的偏导数diff

本博文源于matlab求解多元函数导数。涉及求一阶/求多阶/求向量偏导数/求隐函数导数 多元函数的偏导数 diff(f(x,y,z),变量名)例子 求x^2lny根号z的偏导数 >> syms x >> syms y >> syms z >> du_dx diff(x^2log(y)sqrt(z),x)du_dx 2*x>> du_dz…

matlab实现隐函数求偏导数(impldiff函数)

目录 总述函数说明应用举例例1例2 函数实现 总述 由前面给出的算法&#xff0c;可以编写出如下函数来求解隐函数的偏导数。 函数说明 function dy impldiff(f, x, y, n) %impldiff %隐函数求导 % 调用格式&#xff1a; % f1 impldiff(f, x, y, n) % 其中&#xff1a;f…

matlab偏导数方程,利用Matlab求解不同类型的偏微分方程

来源:新浪了凡春秋的博客 在科学技术各领域中,有很多问题都可以归结为偏微分方程问题。在物理专业的力学、热学、电学、光学、近代物理课程中都可遇见偏微分方程。偏微分方程,再加上边界条件、初始条件构成的数学模型,只有在很特殊情况下才可求得解析解。随着计算机技术的发…

【MATLAB】求偏导数

目录 1、示例1 2、示例2 3、MATLAB求偏导数的应用 1、示例1 syms x y; z=(1+x*y)^y; zx=diff (z,’x’)

MATLAB求解偏导数

MATLAB具有多元函数求解偏导数的功能。 例&#xff1a; 1.函数关于x的二阶偏导数 syms x y >> z x^4y^4-4*x^2*y^2; >> zxx diff(z,x,2)zxx 12*x^2 - 8*y^2 2.函数关于y的二阶偏导数 zyy diff(z,y,2)zyy 12*y^2 - 8*x^2 3.函数二阶混合偏导数 zxy diff(dif…

MATLAB常用求导和求偏导函数

matlab求导命令diff调用格式: diff(函数) &#xff0c; 求的一阶导数&#xff1b;diff(函数&#xff0c; n) &#xff0c;求的n阶导数(n是具体整数)&#xff1b;diff(函数&#xff0c;变量名)&#xff0c;求对的偏导数&#xff1b;diff(函数&#xff0c; 变量名&#xff0c;n)…

性能测试流程(完整版)

一、 规范性能测试实施流程的意义 规范的性能测试实施流程能够加强测试工作流程控制&#xff0c;明确性能测试各阶段应完成的工作&#xff0c;指导测试人员正确、有序的开展性能测试工作&#xff0c;提高各角色在性能能测试中的工作效率。本次分享的性能测试实施流程是性能测试…

性能测试流程相关

1、脚本制作流程 脚本制作方法可参考此链接&#xff1a;性能测试脚本实战_HealerLX的博客-CSDN博客 &#xff08;1&#xff09;抓包工具抓包 &#xff08;2&#xff09;录入到性能测试工具中 &#xff08;3&#xff09;调试脚本直到成功 &#xff08;4&#xff09;加上运行逻辑…

性能测试流程、优化、指标

性能测试流程、优化、指标 1、性能测试的流程 1、确定性能测试的目标 之前做的压测性能标准、产品说明书的性能需求部分、运营人员提出的性能指标、通过生产环境换算出的性能指标等 &#xff08;1&#xff09;接口响应时间不能超过3秒&#xff08;每个接口的响应时间&#…