Timer与TimerTask详解

2024-04-05 02:58
文章标签 详解 timer timertask

本文主要是介绍Timer与TimerTask详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.概览

有时候需要提前安排将来某段时间执行某任务,你可以使用Timer,TimerTask两个类创建后台进程,让其在等待一段规定的时间后执行,或者让其每隔一段时间执行。你也可以用Thread来完成,但利用TimerTimerTask显然省事不少。

TimerTask实现了Runnable接口,待执行的任务置于run()中。Timer是一个安排TimerTask的类,两者一般一起工作。所以在应用时首先要创建一个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线程:

调用timercancle方法。你可以从程序的任何地方调用此方法,甚至在一个timer taskrun方法里。 

timer线程成为一个daemon线程(可以在创建timer时使用new Timer(true)达到这个目地),这样当程序只有daemon线程的时候,它就会自动终止运行。 

timer相关的所有task执行完毕以后,删除所有此timer对象的引用(置成null),这样timer线程也会终止。 

调用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.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.进一步分析schedulescheduleAtFixedRate

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

23个参数的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。说白了,这个方法更注重保持间隔时间的稳定。

33个参数的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类的线程安全的。

这篇关于Timer与TimerTask详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/877480

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML