threadx为什么不能在timertask 定时任务中创建任务

ThreadXUserGuide-中文手册_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
ThreadXUserGuide-中文手册
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩70页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢Java定时任务:利用java Timer类实现定时执行任务的功能
作者:51kata
字体:[ ] 类型:转载 时间:
本篇文章主要介绍了利用java Timer类实现定时执行任务的功能,具有一定的参考价值,有需要的可以了解一下。
在java中实现定时执行任务的功能,主要用到两个类,Timer和TimerTask类。其中Timer是用来在一个后台线程按指定的计划来执行指定的任务。
TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务,具体要执行的代码写在TimerTask需要被实现的run方法中。
二、先看一个最简单的例子
我们通过代码来说明
import java.text.SimpleDateF
import java.util.D
import java.util.T
import java.util.TimerT
public class TimerDemo {
public static String getCurrentTime() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
public static void main(String[] args) throws InterruptedException {
System.out.println("main start:"+getCurrentTime());
startTimer();
Thread.sleep(1000*5); //休眠5秒
System.out.println("main
end:"+getCurrentTime());
public static void startTimer(){
TimerTask task = new TimerTask() {
public void run() {
System.out.println("task
run:"+getCurrentTime());
Timer timer = new Timer();
timer.schedule(task, 0);
为了便于通过打印观察信息,我们在main方法中加了些打印信息,并调用Thread.sleep让主线程休眠一下。另外在类中增加了一个获取当前日期的getCurrentTime方法。
上面的代码,在startTimer方法中,先创建了一个TimerTask对象(将要被定时器执行的任务),然后创建了一个Timer对象,然后调用Timer类的schedule方法。Timer类有多个带不同参数的schedule方法。这里用到的是: 
public void schedule(TimerTask task, long delay)
该方法的含义是,表示定时器将延迟delay(毫秒)时间后,执行task任务。如果delay为负数或0,则任务会被立即进行。而且是一次性的执行任务,后续不会重复(或定时)执行该任务。
对于Timer类,还提供一个同样功能的方法,如下: 
public void schedule(TimerTask task, Date time)
该方法与上面方法的区别是,上面方法是指定延期一段时间执行,这个方法是指定在某个具体的时间点执行。注意,如果系统的当前时间已经超过了参数time指定的时间,该任务会被立即执行。
当运行上面代码时,我们发现程序立即打印类似如下的2条信息:
main start: 22:23:18
task&& run: 22:23:18
因为我们这里给schedule方法传递的delay参数值为0,所以任务会被立即执行,所以两个语句打印出来的时间是一样的,这是应该的。大家可以自己改变传入的delay值来看输出信息的变化。再过大约5秒(即sleep的时间)后,继续打印了1条信息:
main&& end: 22:23:23
打印信息的时间与上面语句差了5秒,与sleep设置的一致,也是很合理的。
但我们会发现一个很有趣的现象,会发现该进程不会退出,这时main主线程已经结束了,这说明定时器把任务完成后,即使后面没有待等待执行的任务了,定时器中创建的后台线程也不会立即退出。查看了相关的java doc文档,解释说定时器线程不会主动退出,需要等待垃圾回收,但java的待垃圾回收是无法通过代码自己控制的,而是由虚拟机控制的。
研究了下,发现在创建Timer对象,及执行Timer timer = new Timer(); 语句时,定时器线程就会被创建。也就是说即使上面代码没有timer.schedule(task, 0);这个语句,程序也不会退出。感觉这个挺不合理的。再次研究了下Timer类的源代码,发现其还有一个带布尔参数的构造函数:
public Timer(boolean isDaemon)
从参数名就可以看出,如果参数值为true时,则Timer创建的定时器线程为守护线程。守护线程的含义是,当java进程中所有的工作线程都退出后,守护线程就自动退出了。
这时我们只要把上面例子中的创建Timer对象的代码改为:Timer timer = new Timer(true);
发现运行程序后,等main线程(main线程不是守护线程,是工作线程)结束后,程序会退出,也就是说定时器线程也退出了,说明加上参数true后,创建的它是守护线程了。
但问题是,在真正的应用场景中,有很多工作线程在运行,程序不会随便退出。那如果要想定时器能立即退出或关闭,该怎么办呢?这个我们下面介绍。
三、定时器的退出
Timer类提供了一个cancel方法可以取消定时器。调用cancel方法会终止此计时器,丢弃所有当前已安排的任务。这不会干扰当前正在执行的任务(如果存在)。一旦终止了计时器,那么它的执行线程也会终止,并且无法根据它安排更多的任务。
注意,在此计时器调用的计时器任务的 run 方法内调用此方法,就可以绝对确保正在执行的任务是此计时器所执行的最后一个任务。可以重复调用此方法;但是第二次和后续调用无效。
我们再看一个例子代码:
import java.text.SimpleDateF
import java.util.D
import java.util.T
import java.util.TimerT
public class TimerDemo {
public static String getCurrentTime() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
public static void main(String[] args) throws InterruptedException {
System.out.println("main start:"+getCurrentTime());
Timer timer = startTimer();
Thread.sleep(1000*5); //休眠5秒
System.out.println("main
end:"+getCurrentTime());
timer.cancel();
public static Timer startTimer(){
TimerTask task = new TimerTask() {
public void run() {
System.out.println("task
run:"+getCurrentTime());
Timer timer = new Timer();
timer.schedule(task, 0);
运行程序,跟上面一个例子的输出情况完全一样。区别是,当main方法结束后。进程会主动退出,也就是说定时器线程已经关闭了。
因为我们在main方法中调用了cancel方法。 注意,如果不是在TimerTask的run方法中调用cancel方法一定要注意,一定要确保希望执行的任务已经开始执行或执行完毕,否则如果任务还未开始执行。就调用cancel,则所有任务都不会被执行了。比如上面的代码,
比如上面的代码,如果我们不在main方法中调用cancel方法,而是在startTimer方法中 timer.schedule(task, 0); 语句后加上timer.cancel();语句,运行后会发现,定时器任务不会被执行,因为还未来得及执行就被取消中止了。
四、定时执行任务
上面的例子,我们介绍的是一次性任务,也就是定时器时间到了,执行完任务,后面不会再重复执行。在实际的应用中,有很多场景需要定时重复的执行同一个任务。这也分两种情况,一是每隔一段时间就执行任务,二是每天(或每周、每月等)的固定某个(或某几个)时间点来执行任务。
我们先来看第一种情况,实现每隔10秒执行同一任务的例子。代码如下:
import java.text.SimpleDateF
import java.util.D
import java.util.T
import java.util.TimerT
public class TimerDemo {
public static String getCurrentTime() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
public static void main(String[] args) throws InterruptedException {
System.out.println("main start:"+getCurrentTime());
startTimer();
public static void startTimer(){
TimerTask task = new TimerTask() {
public void run() {
System.out.println("task
run:"+getCurrentTime());
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
Timer timer = new Timer();
timer.schedule(task, 0*10);
执行上述程序,输出信息如下(因为定时器没有停止,重复执行任务,会不断输出,这里只拷贝了前面的一些输出)
main start: 08:41:14
task&& run: 08:41:19
task&& run: 08:41:29
task&& run: 08:41:39
task&& run: 08:41:49
task&& run: 08:42:00
task&& run: 08:42:10
task&& run: 08:42:20
task&& run: 08:42:30
task&& run: 08:42:40
在上面的代码中,我们调用了 timer.schedule(task, 0*10); 这个含义是该任务延迟5秒后执行,然后会每隔10秒重复执行。我们观察输出信息中打印的时间,是与预期一样的。 另外可以看出,间隔是以任务开始执行时间为起点算的,也就是并不是任务执行完成后再等待10秒。
Timer类有两个方法可以实现这样的功能,如下:
public void schedule(TimerTask task, long delay, long period)
public void schedule(TimerTask task, Date firstTime, long period)
我们上面代码用的是第一个方法。两个方法区别在于第一次执行的时间,第一个方法是在指定延期一段时间(单位为毫秒)后执行;第二个方法是在指定的时间点执行。
这时我们考虑如下场景,如果某个任务的执行耗时超过了下次等待时间,会出现什么情况呢? 我们还是通过代码来看:
import java.text.SimpleDateF
import java.util.D
import java.util.T
import java.util.TimerT
public class TimerDemo {
public static String getCurrentTime() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
public static void main(String[] args) throws InterruptedException {
System.out.println("main start:"+getCurrentTime());
startTimer();
public static void startTimer(){
TimerTask task = new TimerTask() {
public void run() {
System.out.println("task begin:"+getCurrentTime());
Thread.sleep(1000*10);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("task
end:"+getCurrentTime());
Timer timer = new Timer();
timer.schedule(task, 0*5);
与前面代码相比,我们只改了2处代码和修改了下打印,一是将run方法中的sleep改为了10秒,二是将任务的执行周期改为5秒。也就说任务的执行耗时超过了任务重复执行的间隔。运行程序,前面的输出如下:
main start: 09:03:51
task begin: 09:03:56
task&& end: 09:04:06
task begin: 09:04:06
task&& end: 09:04:16
task begin: 09:04:16
task&& end: 09:04:26
task begin: 09:04:26
task&& end: 09:04:36
task begin: 09:04:36
task&& end: 09:04:46
task begin: 09:04:46
task&& end: 09:04:56
可以看出,每个任务执行完成后,会立即执行下一个任务。因为从任务开始执行到任务完成的耗时已经超过了任务重复的间隔时间,所以会重复执行。
五、定时执行任务(重复固定时间点执行)
我们来实现这样一个功能,每天的凌晨1点定时执行一个任务,这在很多系统中都有这种功能,比如在这个任务中完成数据备份、数据统计等耗时、耗资源较多的任务。代码如下:
import java.text.SimpleDateF
import java.util.C
import java.util.D
import java.util.T
import java.util.TimerT
public class TimerDemo {
public static String getCurrentTime() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
public static void main(String[] args) throws InterruptedException {
System.out.println("main start:" + getCurrentTime());
startTimer();
public static void startTimer() {
TimerTask task = new TimerTask() {
public void run() {
System.out.println("task begin:" + getCurrentTime());
Thread.sleep(1000 * 20);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("task
end:" + getCurrentTime());
Timer timer = new Timer();
timer.schedule(task, buildTime(), 1000 * 60 * 60 * 24);
private static Date buildTime() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date time = calendar.getTime();
if (time.before(new Date())) {
//若果当前时间已经是凌晨1点后,需要往后加1天,否则任务会立即执行。
//很多系统往往系统启动时就需要立即执行一次任务,但下面又需要每天凌晨1点执行,怎么办呢?
//很简单,就在系统初始化话时单独执行一次任务(不需要用定时器,只是执行那段任务的代码)
time = addDay(time, 1);
private static Date addDay(Date date, int days) {
Calendar startDT = Calendar.getInstance();
startDT.setTime(date);
startDT.add(Calendar.DAY_OF_MONTH, days);
return startDT.getTime();
因为是间隔24小时执行,没法等待观察输出。
本文介绍了利用java Timer类如何执行定时任务的机制。可以看出,还是有许多需要注意的方法。 本文中介绍的例子,每个定时器只对应一个任务。
本文介绍的内容可以满足大部分应用场景了,但还有一些问题,比如对于一个定时器包括多个任务?定时器取消后能否再次添加任务?Timer类中还有哪些方法可用? 这些问题,我们再后面的博文中介绍。
原文链接:/51kata/p/5128745.html
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具threadx源码学习_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
threadx源码学习
&&学习THREADX资料
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩43页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
threadx源码学习
下载积分:800
内容提示:threadx源码学习
文档格式:DOC|
浏览次数:42|
上传日期: 08:58:30|
文档星级:
全文阅读已结束,如果下载本文需要使用
 800 积分
下载此文档
该用户还上传了这些文档
threadx源码学习
官方公共微信69082人阅读
05 JavaSE(61)
这两个类使用起来非常方便,可以完成我们对定时器的绝大多数需求
Timer类是用来执行任务的类,它接受一个TimerTask做参数
Timer有两种执行任务的模式,最常用的是schedule,它可以以两种方式执行任务:1:在某个时间(Data),2:在某个固定的时间之后(int delay).这两种方式都可以指定任务执行的频率
TimerTest.java:
import java.io.IOE
import java.util.T
public class TimerTest{
public static void main(String[] args){
Timer timer = new Timer();
timer.schedule(new MyTask(), );//在1秒后执行此任务,每次间隔2秒执行一次,如果传递一个Data参数,就可以在某个固定的时间执行这个任务.
while(true){//这个是用来停止此任务的,否则就一直循环执行此任务
int in = System.in.read();
if(in == 's'){
timer.cancel();//使用这个方法退出任务
} catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
static class MyTask extends java.util.TimerTask{
public void run(){
System.out.println(&________&);
此类运行时:
程序启动1秒后在控制台打印“————”
间隔两秒后接着执行MyTask的run()方法,打印“————”
这样一直循环
当在控制台输入s字符时,timer定时器取消工作
跳出整个循环
程序运行结束!
TimerTest2.java:
import java.io.IOE
import java.util.D
import java.util.T
public class TimerTest2{
public static void main(String[] args){
Timer timer = new Timer();
MyTask myTask1 = new MyTask();
MyTask myTask2 = new MyTask();
myTask2.setInfo(&myTask-info-2&);
timer.schedule(myTask1, );
//任务1 一秒钟后执行,每两秒执行一次。
timer.scheduleAtFixedRate(myTask2, );
//任务2 2秒后开始进行重复的固定速率执行(3秒钟重复一次)
while (true){
//用来接收键盘输入的字符串
byte[] info = new byte[1024];
int len = System.in.read(info);
String strInfo = new String(info, 0, len, &GBK&);//从控制台读出信息
if (strInfo.charAt(strInfo.length() - 1) == ' '){
strInfo = strInfo.substring(0, strInfo.length() - 2);
if (strInfo.startsWith(&Cancel-1&)){
myTask1.cancel();//退出任务1
// 其实应该在这里判断myTask2是否也退出了,是的话就应该break.但是因为无法在包外得到
// myTask2的状态,所以,这里不能做出是否退出循环的判断.
} else if (strInfo.startsWith(&Cancel-2&)){
myTask2.cancel();
//退出任务2
} else if (strInfo.startsWith(&Cancel-All&)){
timer.cancel();//退出Timer
// 只对myTask1作出判断,偷个懒^_^
myTask1.setInfo(strInfo);
} catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
static class MyTask extends java.util.TimerTask{
String info = &INFO&;
public void run(){
// TODO Auto-generated method stub
System.out.println(new Date() + &
& + info);
public String getInfo(){
public void setInfo(String info){
此类创建了两个定时任务mytask1和mytask2&
mytask1任务和上面的TimerTest类中的例子用法一样。即安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
mytask2任务就不同于上面的用法了,timer.scheduleAtFixedRate它是用的timer定时器的scheduleAtFixedRate()方法来执行。
scheduleAtFixedRate()方法在API1.6.0中是这样定义的:
安排指定的任务在指定的时间开始进行重复的固定速率执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。
近似固定的时间间隔的意思是说:在固定速率执行中,相对于已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则将快速连续地出现两次或更多次执行,从而使后续执行能够赶上来。
Timer类的常用其他方法:
终止此计时器,丢弃所有当前已安排的任务。
从此计时器的任务队列中移除所有已取消的任务。
安排在指定的时间执行指定的任务。
TimerTask类的常用其他方法:
取消此计时器任务。
此计时器任务要执行的操作。
返回此任务最近实际 执行的已安排 执行时间。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1988068次
积分:16101
积分:16101
排名:第672名
原创:206篇
转载:212篇
评论:140条
(2)(2)(4)(1)(3)(1)(1)(2)(1)(3)(1)(6)(5)(1)(1)(2)(1)(1)(10)(11)(4)(15)(4)(6)(4)(6)(6)(1)(3)(2)(2)(3)(4)(8)(4)(5)(3)(1)(2)(3)(4)(5)(6)(10)(1)(16)(21)(31)(10)(38)(22)(58)(14)(37)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 java timer 取消任务 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信