【测试详解】关于java定时器的常见问题,例如无法取消,被延期执行等

2023-10-30

定时器Timer

  • Timer timer = new Timer(true);将定时器设置为守护线程(daemon),即当用户线程都已经执行完毕退出以后,jvm就会结束守护进程,不管守护进程是否还有任务,程序退出。

定时器任务TimerTask

  • 可以由计时器进行一次性或重复执行的任务,简单来说就是计时器要执行的任务。

ok,把两者联系起来使用就是:

timer.schedule(TimerTask task, long delay, long period)在指定 的延迟之后开始 ,重新执行 固定延迟执行的指定任务。

还有更多API也顺便在这里copy出来,看的时候方便:

    • void cancel()

      终止此计时器,丢弃任何当前计划的任务。

      int purge()

      从该计时器的任务队列中删除所有取消的任务。

      void schedule(TimerTask task, Date time)

      在指定的时间安排指定的任务执行。

      void schedule(TimerTask task, Date firstTime, long period)

      从指定 的时间开始 ,对指定的任务执行重复的 固定延迟执行

      void schedule(TimerTask task, long delay)

      在指定的延迟之后安排指定的任务执行。

      void schedule(TimerTask task, long delay, long period)

      在指定 的延迟之后开始 ,重新执行 固定延迟执行的指定任务。

      void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

      从指定的时间 开始 ,对指定的任务执行重复的 固定速率执行

      void scheduleAtFixedRate(TimerTask task, long delay, long period)

      在指定的延迟之后 开始 ,重新执行 固定速率的指定任务。

其实timer相当于一个后台单线程,timerTask就是timer里面的单个线程任务,timer除非设置成守护线程或则主动使用cancle方法终止计时器,否则会一直执行,而其中独立的timerTask也可以单独调用timerTask.cancle()方法终止任务,但是此方法只是终止了timer其中的某个独立的任务,timer仍然会继续执行:

例如:

Timer timer = new Timer();

TimerTask tt1 = new TimerTask(){public void run(){//执行代码}};

TimerTask tt2 = new TimerTask(){public void run(){//执行代码}};

timer.schedule(tt1,new Date(),5000);

timer.schedule(tt2,1000,5000);

调用其中的tt1的cancle方法只会终止tt1的任务,而timer和tt2任然会继续执行。

【附加说明】串行化特性:

       这样就是把tt1和tt2两个任务放入了timer线程当中串行执行,即tt1执行完才轮到tt2执行,t可以看到tt1和tt2其实应该是同时执行的,但是tt2延迟一秒钟期间,如果tt1还未执行完毕,那么tt2的开始执行时间因而会被推迟到tt1执行完毕后才开始执行,这就是为什么有时候发现为什么没有按时执行,可以从这里分析一下问题原因

 

----timer单线程

  • 对应于每个Timer对象是单个后台线程,用于依次执行所有定时器的所有任务。

public class TestTImerCircle2 {
	public static void main(String[] args) throws InterruptedException {
		Timer t = new Timer();
		//第一个任务
		TimerTask tt1 = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running1");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running1 end");
			}
		};
		//第二个任务
		TimerTask tt2 = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running2");
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running2 end");
			}
		};
		t.schedule(tt2, new Date());
		t.schedule(tt1, new Date());
		
	}
}

 可以看到输出:

running2
running2 end
running1
running1 end

程序未终止

 running2 end执行在running1之前,如果是多线程并行running1会在running2 end之前,此处证明timer是单个线程后台。

需要区别与多线程并行的线程池执行任务:

​
public class ThreadPoolTest{
	public static void main(String[] args) throws InterruptedException {
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		//第一个任务
		Runnable tt1 = new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running1");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running1 end");
			}
		};
		//第二个任务
		Runnable tt2 = new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running2");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running2 end");
			}
		};
		newCachedThreadPool.submit(tt1);
		newCachedThreadPool.submit(tt2);
		newCachedThreadPool.shutdown();
	}
}

​

 如上,tt1和tt2是同时进行的,输出结果是:

running2
running1
running1 end
running2 end

程序终止

----timer的终止

  • 空引用回收:在最后一次对Timer对象的引用后所有未完成的任务已完成执行,定时器的任务执行线程正常终止(并被收集到垃圾回收)。 但是,这可能需要任意长时间的发生。

  • 主动终止计时器:如果主叫方想要快速终止定时器的任务执行线程,则调用者应该调用定时器的cancel方法。


public class TestTImerCircle {
	public static void main(String[] args) {
		Timer t = new Timer();
		TimerTask tt = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running");
			}
		};
		t.schedule(tt, new Date());
        //方法一:置空等待回收
		t = null;
        //方法二:cancle终止
        //t.cancle();
		System.gc();
	}
}

执行结果: 

running

程序终止

以上,如果注释掉最后一行代码,发现很久(非常久,测试几个钟结束)都没有反应,因为jvm回收垃圾发生在任何时候,而主动调用gc回收发现程序立马终止,验证以上结论1。注释掉t=null,取消注释t.cancle()发现running并没有输出而是直接被终止,这是因为任务还没开始执行就被终止了,使用以下代码可以看到输出running:

public class TestTImerCircle2 {
	public static void main(String[] args) throws InterruptedException {
		Timer t = new Timer();
		TimerTask tt = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running");
			}
		};
		t.schedule(tt, new Date());
		Thread.sleep(100);
		t.cancel();
		
//		t = null;
//		System.gc();
		
	}
}

执行结果: 

running

程序终止

最重要的一种情况需要注意,如果任务正在执行,还未执行完,那么cancle()将不会引起正在进行的任务立马结束,而是等待当前任务完成以后,才终止计时器

public class TestTImerCircle2 {
	public static void main(String[] args) throws InterruptedException {
		Timer t = new Timer();
		TimerTask tt = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running end");
			}
		};
		t.schedule(tt, new Date());
		Thread.sleep(100);
		t.cancel();
		
//		t = null;
//		System.gc();
		
	}
}

执行结果: 

running

等待2秒钟

running end

程序终止

可以看到,两秒后才输出running end,另外cancle一旦触发,不管是否设置了重复执行,只要当前没有正在执行中的任务,立刻终止计时器: 

public class TestTImerCircle2 {
	public static void main(String[] args) throws InterruptedException {
		Timer t = new Timer();
		TimerTask tt = new TimerTask() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("running");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println("running end");
			}
		};
		t.schedule(tt, new Date(),1);
		Thread.sleep(100);
		t.cancel();
		
//		t = null;
//		System.gc();
		
	}
}

执行结果:

running

执行2秒钟后

running end

程序终止

以上设置了隔1毫秒执行一次,但是执行完第一次后程序立刻被结束退出了,此处证明cancle具有延迟生效特性(有正在执行的任务)和必定执行特性(代码一旦被执行,必定在下一次任务前终止计时器)。

 

以上就介绍这么多,timer和timertask的使用应该足够了,然后还有一个是purge这个方法,从该计时器的任务队列中删除所有取消的任务,返回删除数,不知道为什么测试总是0,后续有空再更新测试吧。

 

 

对了,以上例子因为使用了timer.schedule(TimerTask timerTask,Date time)这个方法,在指定的时间安排指定的任务执行,并且只执行一次,所以如果碰到需要使用timer.schedule(TimerTask timerTask,Date time,long period)这种方法来重复间隔执行任务的情况,而达到条件要取消掉其中的一个timertask,那就可以在timertask的实现方法run中加入this.cancle()即可把timer中的该任务取消掉了,接着应该就可以使用timer.purge()这个方法清除掉,也可以不使用,等待jvm回收即可。

TimerTask tt2 = new TimerTask() {
			@Override
			public void run() {
				// 达到条件,结束
				this.cancle();
			}
		};

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【测试详解】关于java定时器的常见问题,例如无法取消,被延期执行等 的相关文章

  • Objective-C:在 SpriteKit 中向计时器添加 10 秒

    我使用了别人的代码在 SpriteKit 中编写计时器 并对其进行了一些调整 我的代码如下所示 void createTimerWithDuration NSInteger seconds position CGPoint position
  • Websphere Liberty Profile 中的 Java EE-Timer / @Schedule

    我想使用计时器服务 特别是 Schedule注解 http docs oracle com javaee 6 api javax ejb Schedule html 在 WebSphere Liberty Profile 中 那可能吗 有一
  • 计时器和 JFrame 错误

    我正在制作一个带有计时器和 JFrame 的游戏 以及许多其他东西 但只有这两个会引起问题 在运行下面的片段后 我收到了一个奇怪的错误 至少对于之前从未使用过这些类的我来说是这样 开始执行这个 private static GameView
  • 有没有办法暂停所有 Threading.Timer 计时器?

    我是 C 新手 正在开发一个需要多个计时器的程序 我想知道当程序运行 CPU 密集型代码时是否有办法同时暂停该程序中的所有计时器 目前 当前启用的计时器尝试赶上密集操作期间引发的所有计时器事件 我认为您可以创建这些计时器的列表 当您激活它们
  • java.util.Timer:它是否已弃用?

    我在评论中读到这个答案 https stackoverflow com questions 2212848 how to genarate random numbers 2212887 2212887以及许多其他有关日程安排的问题 抱歉 没
  • 如何在 iOS 7 中让 NSTimer 在后台运行超过 180 秒?

    我已经尝试过 但在 iOS 7 和 Xcode 4 6 2 中工作时间不超过 180 秒 请帮我 UIBackgroundTaskIdentifier bgTask UIBackgroundTaskInvalid UIApplication
  • 如何立即触发timer.Elapsed事件

    我正在使用System Timers Timer类来创建一个计时器Timer Elapsed事件 事情是Timer Elapsed仅在间隔时间过去后才会首次触发事件 有没有办法提高Timer Elapsed启动计时器后立即发生事件 我在中找
  • 定时器在待机模式下会发生什么情况? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在运行时更改android中睡眠/定时器线程的延迟?

    我试图做的是每次计数器变为 5 的倍数时减少计时器延迟 但是 一旦代码进入 if 块 它就停止递增计时器 我不明白发生了什么事 这是代码 thread new Thread public void run try if count 5 0
  • 当 Activity 不在前面时,暂停 Android 中的 CountDownTimer

    我有一个使用从 10 开始倒数的 CountDownTimer 的活动 当该活动不再处于焦点时 例如用户接到电话或其他情况 如何暂停该计时器 然后在用户返回时恢复计时器活动 这可能吗 我会向 onTick 处理程序添加一些内容 以保存类中计
  • Android:定时器/延迟替代方案

    我想让一个图像在 60 毫秒内可见 然后不可见 然后我想让另一个图像执行相同的操作 等等 我认为我没有正确使用计时器 因为当我运行该应用程序时 两个图像会同时打开 并且当我按下使用此功能的按钮时 两个图像不会消失 这是一些示例代码 time
  • Linux下如何用C实现定时器的回调函数

    我已经在许多论坛上搜索了几天可能的解决方案 但没有运气 我在这里发布我的问题 非常感谢您的回复 主意 使用脚本控制灯光 Linux下C语言 应用场景 我有三盏灯 红 蓝 绿 脚本有控制它们的时间表 例如 从现在起10秒后 亮红灯2秒 从现在
  • Angular2 可观察定时器条件

    我有一个计时器 initiateTimer if this timerSub this destroyTimer let timer TimerObservable create 0 1000 this timerSub timer sub
  • 在JTextArea中使用Timer实现打字机效果?

    我正在制作一款文本冒险游戏 但遇到了一个问题 我无法按照我想要的方式显示一些文本 当输入一些单词时 玩家可以开始引入一个新房间 我希望这个介绍具有 打字机 效果 该事件需要在我的程序 ActionPerformed 方法中发生 例如 当用户
  • WPF C# - 计时器倒计时

    如何在用 WPF C 编写的代码中实现以下内容 我有一个 ElementFlow 控件 在其中实现了 SelectionChanged 事件 该事件 根据定义 在控件的项目选择发生更改时触发特定事件 我想要它做的是 启动计时器 如果计时器达
  • 互动倒计时增加?

    我有一个表单 如果没有完成任何鼠标交互 我想在 5 秒后关闭它 但如果完成任何鼠标交互 我希望它关闭countdown 5 seconds每次交互都会增加 5 秒 这是我到目前为止想到的 int countdown 5 System Tim
  • 使用 IcyStreamMeta 从 SHOUTcast 获取元数据

    我正在为 Android 编写一个应用程序 从 SHOUTcast mp3 流中获取元数据 我正在使用我在网上找到的一个非常漂亮的类 我稍微修改了一下 但我仍然有两个问题 1 我必须使用 TimerTask 不断 ping 服务器来更新元数
  • Android 计时器/计时器任务导致我的应用程序崩溃?

    只是在我的 mainActivity 的 onCreate 中测试一个简单的代码块 Timer timer2 new Timer TimerTask testing new TimerTask public void run Toast m
  • C#,System.Timers.Timer,每 15 分钟运行一次,与系统时钟同步

    如何让 System Timers Timer 每 15 分钟触发一次与系统时钟同步的事件 换句话说 我希望它恰好在 xx 00 xx 15 xx 30 xx 45 触发 其中 xx 表示任何小时 您可以让它每秒流逝一次 并检查当前时间是否
  • 如何使用 Python 3 正确显示倒计时日期

    我正在尝试获取将显示的倒计时 基本上就像一个世界末日时钟哈哈 有人可以帮忙吗 import os import sys import time import datetime def timer endTime datetime datet

随机推荐

  • MATLAB&机器学习进阶

    本文借鉴了数学建模清风老师的课件与思路 可以点击查看链接查看清风老师视频讲解 清风数学建模 https www bilibili com video BV1DW411s7wi 目录 一 K最近邻 KNN 二 决策树 三 支持向量机 四 集成
  • 喜欢就争取,得到就珍惜,错过就忘记—dbGet(二)

    通过前面一篇对dbGet基本用法的介绍 大家应该对它有一定了解了吧 那接来下 我们就要学习一下进阶的dbGet用法了 dbGet是由它基本的语法加上各种object的attribute的组合构成的 大家在熟悉基本语法之后 就应该去学习各个o
  • OpenThread is an Open Source Implementation of Thread IoT Networking Protocol

    本文转载至 http www cnx software com 2016 05 12 openthread is an open source implementation of thread iot networking protocol
  • zabbix邮件报警配置

    前言 Zabbix监控服务端 客户端都已经部署完成 被监控主机已经添加 Zabiix监控运行正常 在Zabbix服务端设置邮件报警 当被监控主机宕机或者达到触发器预设值时 会自动发送报警邮件到指定邮箱 邮件服务可以使用系统自带的邮件服务来发
  • linuxrpm命令卸载python_Linux RPM包安装、卸载、升级命令讲解

    一个 RPM 包包含了已压缩的软件文件集以及该软件的内容信息 通常表现为以 rpm 扩展名结尾的文件 例如 samba rpm 如果需要对RPM包进行操作则需要使用rpm命令 一 RPM包的来源 所有RPM包都在系统光盘的Packages目
  • coco数据集80个分类是哪些_目标分类定位,实时速度检测...目标检测5大挑战与解决方案...

    图像分类是指计算机根据图像内容对图像进行分类或分配标签 通常只需利用预先训练好的神经网络 对最后几个吞吐量层进行微调 然后就可以看到很好的结果 然而 仅在几年前 对图像中的单个目标进行分类和查找未知数量是极其困难的 现在 这项被称为目标检测
  • HTML 标签

    定义和用法 声明必须是 HTML 文档的第一行 位于 标签之前 声明不是 HTML 标签 它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令 在 HTML 4 01 中 声明引用 DTD 因为 HTML 4 01 基于
  • uinapp和php实现RSA + AES 双向通信加密

    使用场景 如果只是为了防止用户数据泄露 有条件用https 那不要犹豫 赶快买个证书 但是https也有局限性 加密层位于http层 应用层 和tcp层 传输层 之间 所以抓到的http层的数据并没有加密 单独加密的弊端 单独用RSA非对称
  • QT5.12.3+OPENCV4.2.0配置,MINGW编译与库文件调用

    目录 1 QT5 12 3 OPENCV4 2 0 2 准备工作 3 安装步骤 3 1 QT 3 2 CMAKE 3 3 OPENCV 4 使用MINGW编译OPENCV 5 QT调用库文件 6 QT测试OPENCV 1 QT5 12 3
  • PyTorch简介及环境搭建

    本文主要包含PyTorch的基本介绍 以及安装方法 文章目录 前言 PyTorch简介 PyTorch作用 对比PyTorch和Tensorflow PyTorch大版本的主要更新 PyTorch总结 PyTorch环境搭建 安装PyTor
  • python基础总结:1.9、错误和异常

    python基础总结 1 9 错误和异常 文章目录 python基础总结 1 9 错误和异常 1 语法错误 2 异常 3 处理异常 4 抛出异常 5 用户自定义异常 6 定义清理操作 7 预定义的清理操作 到目前为止 我们还没有提到错误消息
  • zabbix3.4.2使用discovery对磁盘IO进行监控

    https blog csdn net m0 37814112 article details 80997967
  • c++ 代码

    js 调用c 代码给的接口 c 代码储存在exe和dll文件中 转载于 https www cnblogs com guomengkai p 11502475 html
  • 74HC595芯片——单芯片控制代码示例

    1 关于74HC595 芯片示意图 TSSOP封装 引脚说明 符号 引脚 描述 Q0 Q7 第15脚 第1 7脚 8位并行数据输出 GND 第8脚 地 Q7 第9脚 串行数据输出 MR 第10脚 主复位 低电平有效
  • Sklearn工具包及模型评估

    一 Sklearn工具包介绍 scikit learn 又写作sklearn 是一个开源的基于python语言的机器学习工具包 它通过NumPy SciPy和Matplotlib等python数值计算的库实现高效的算法应用 并且涵盖了几乎所
  • vcs覆盖率选项

    vcs中常用的收集覆盖率选项如下 1 cm dir
  • 【RuoYi-Vue-Plus】学习笔记 05 - 日志框架 TLog

    文章目录 参考资料 一 概述 二 相关配置 1 Maven 2 Logback框架适配器 3 自动打印调用参数和时间 4 TLogConfig 参考资料 1 TLog官方文档 2 TLog官方文档 按需依赖 3 TLog官方文档 Logba
  • kaggle免费GPU,google人机认证

    45条消息 GOOGLE 人机验证 RECAPTCHA 无法显示解决方案 转 散着步的码农的博客 CSDN博客x 许多小伙伴想找免费GPU kaggle确实是个非常不错的选择 本人亲测 配合抖音明日科技还是什么博主和这个博客 可以轻松解决
  • 【IT之路】Docker拉取镜像查看版本

    Docker拉取镜像查看版本 需要在docker hub查看 地址如下 https hub docker com 进入之后 在页面左上角搜索框搜索 以CentOS为例
  • 【测试详解】关于java定时器的常见问题,例如无法取消,被延期执行等

    定时器Timer Timer timer new Timer true 将定时器设置为守护线程 daemon 即当用户线程都已经执行完毕退出以后 jvm就会结束守护进程 不管守护进程是否还有任务 程序退出 定时器任务TimerTask 可以