java 定时_结合真实案例,清晰梳理几种定时任务的退出「JAVA并发」
工作中常常会有定时任务的开发需求,特别是移动端。最近笔者正好有所涉及,鉴于此,结合开发中的案例说明一下几种定时任务的退出。
需求说明:定时更新正在生成的文件大小和状态【进行中、失败、完成】,如果文件生成完成,则退出【CoderBaby】
调度可以用Timer 【调用schedule()或者scheduleAtFixedRate()方法实现】或者ScheduledExecutorService 【结合工作中其它的需求,笔者选用此】
ScheduledExecutorService的初始化(线程池):
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
- 手动实现——最朴素的方案【通过sleep来控制时间间隔、break来退出】
scheduledExecutorService.execute(() -> { long oldCurFileSize = 0; while(true) { try { Thread.sleep(updateInternal * 1000); long curFileSize = Files.size(Paths.get(TMP_PCAP_PATH + tmpPcapFileName)); int status = getStatus(tmpPcapFileName); if (isFailed(status) || hasNoData(status) || isFinished(status)) { break; } if (curFileSize != oldCurFileSize) { updateFileInfo(tmpPcapFileName, curFileSize, 0); oldCurFileSize = curFileSize; } else { updateFileInfo(tmpPcapFileName, curFileSize, 3); // 延迟1秒,才能成功更新 Thread.sleep(1000); break; } } catch (Exception e) { logger.warn("Catch exception : " + e.toString()); } } });
注:
updateFileInfo—更新数据库相关记录;
getStatus—查询数据库当前记录的状态,判定是否完成或者出现错误;
updateInternal—控制定时任务的运行时间间隔(单位为秒)
- TimerTask【通过cancel来退出】
定义一个内部类继承自TimerTask抽象类
class ScheduledUpdateTrafficForensics extends TimerTask { private String tmpPcapFileName; private long oldCurrentFileSize = 0; public ScheduledUpdateTrafficForensics(String tmpPcapFileName) { this.tmpPcapFileName = tmpPcapFileName; } public void run() { try { long currentFileSize = Files.size(Paths.get(TMP_PCAP_PATH + tmpPcapFileName)); int status = getStatus(tmpPcapFileName); if (isFailed(status) || hasNoData(status) || isFinished(status)) { this.cancel(); } if (oldCurrentFileSize != currentFileSize) { updateFileInfo(tmpPcapFileName, currentFileSize, 0); oldCurrentFileSize = currentFileSize; } else { updateFileInfo(tmpPcapFileName, currentFileSize, 3); this.cancel(); } } catch (IOException e) { logger.warn("Catch exception : " + e.toString()); } } }
通过scheduleAtFixedRate接口来调用(设置时间间隔和且第一次执行的延迟时间)
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new ScheduledUpdateTrafficForensics(tmpPcapFileName), updateInternal, pcapDownloadStatusUpdateInternal, TimeUnit.SECONDS);
- ScheduledFuture【通过cancle和读取isCancelled结果来退出】
定义一个内部类实现Runnable接口
class ScheduledUpdateTrafficForensics implements Runnable { private String tmpPcapFileName; private long oldCurrentFileSize = 0; public ScheduledUpdateTrafficForensics(String tmpPcapFileName) { this.tmpPcapFileName = tmpPcapFileName; } public void run() { while (!scheduledFuture.isCancelled()) { try { long currentFileSize = Files.size(Paths.get(TMP_PCAP_PATH + tmpPcapFileName)); int status = getStatus(tmpPcapFileName); if (isFailed(status) || hasNoData(status) || isFinished(status) { scheduledFuture.cancel(true); return; } if (oldCurrentFileSize != currentFileSzie) { updateFileInfo(tmpPcapFileName, currentFileSize, 0); oldCurrentFileSize = currentFileSize; } else { updateFileInfo(tmpPacpFileName, currentFileSize, 3); scheduleFuture.canle(true); } } catch (IOException e) { logger.warn("Catch exception : " + e.toString()); } } } }
通过scheduleAtFixedRate接口来调用(设置时间间隔和且第一次执行的延迟时间),并且将结果返回给ScheduledFuture
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new ScheduledUpdateTrafficForensics(tmpPcapFileName), updateInternal, pcapDownloadStatusUpdateInternal, TimeUnit.SECONDS);
注:
通过scheduledFuture.cancel(true)后可能不能成功结束定时任务,所以必须通过手动调用isCancelled()来判断是否被cancle(调用cancel后,再调用isCancelled() 【一定会返回true】)掉了,然后退出任务。相关源码注释如下:
*
After this method returns, subsequent calls to {@link #isDone} will * always return {@code true}. Subsequent calls to {@link #isCancelled} * will always return {@code true} if this method returned {@code true}.
特别说明:
关于schedule(时间基准:运行的实际时间)和scheduleAtFixedRate(时间基准:理论时间点)的区别:
- scheduleAtFixedRate调度一个task,在delay(ms)后开始调度,然后每经过period(ms)再次调度,貌似和方法—schedule是一样的,其实不然。
- schedule在计算下一次执行的时间的时候,是通过当前时间(在任务执行前得到) + 时间片,而scheduleAtFixedRate方法是通过当前需要执行的时间(也就是计算出现在应该执行的时间)+ 时间片,前者是运行的实际时间,而后者是理论时间点。
例如:schedule时间片是5s,那么理论上会在5、10、15、20这些时间片被调度,但是如果由于某些CPU征用导致未被调度,假如等到第8s才被第一次调度,那么schedule方法计算出来的下一次时间应该是第13s而不是第10s,这样有可能下次就越到20s后而被少调度一次或多次,而scheduleAtFixedRate方法就是每次理论计算出下一次需要调度的时间用以排序,若第8s被调度,那么计算出应该是第10s,所以它距离当前时间是2s,那么再调度队列排序中,会被优先调度,那么就尽量减少漏掉调度的情况。
同样的,我还整理了一部分其他的学习资料,相应源码文档正逐步上传到git中,需要我的git地址的,关注+转发后,私信【git】即可查看地址
java 定时_结合真实案例,清晰梳理几种定时任务的退出「JAVA并发」相关推荐
- 接收不到其他机器发来的报文_大厂真实案例:线上四台机器同一时间全部 OOM......
# 案发现场 昨天晚上突然短信收到 APM (即 Application Performance Management 的简称,我们内部自己搭建了这样一套系统来对应用的性能.可靠性进行线上的监控和预警 ...
- android java框架_【阿里P8大牛教你Android入门之路(java篇)】——Java集合框架(系列篇1)...
一.前言 本部分内容主要包含以下: Java集合 Java反射 Java注解 Java反射 Java IO 其他面试点 以上内容都是Java中的基础知识,对于Java的学习很有帮助.其中集合.反射.I ...
- java 耗时 框架_真真香!耗时大半个月收整全套「Java架构进阶pdf」没白费
2020年的"金九银十"就这么来了,也到了该发福利的阶段了,花了我大半个月时间收整了全套的「Java架构进阶pdf」,这一波下来,刷完你就会知道,真真香啊,我的心血果然,没白费! ...
- java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...
- 超级酒吧女生Java下载_超真实分享:一个人去酒吧的经验+注意事项
原标题:超真实分享:一个人去酒吧的经验+注意事项 今天想跟大家分享我自己一个很奇妙也很特别的经验,就是关于我自己一个人去酒吧喝酒的故事-对这个故事有好奇心的女孩欢迎跟我一起聊聊- 我的个性很独立而且蛮 ...
- go java性能_服务端I/O性能大比拼:Node、PHP、Java和Go
理解应用程序的输入/输出(I/O)模型,意味着其在计划处理负载与残酷的实际使用场景之间的差异.若应用程序比较小,也没有服务于很高的负载,也许它影响甚微.但随着应用程序的负载逐渐上涨,采用错误的I/O模 ...
- node和java性能_服务端I/O性能大比拼:Node、PHP、Java和Go(二)
服务端I/O性能大比拼:Node.PHP.Java和Go(二) 服务端I/O性能大比拼:Node.PHP.Java和Go(二) ### 多线程的方式:Java 所以就在你买了你的第一个域名的时候,Ja ...
- java定时开始和关闭_springboot自带定时器实现定时任务的开启关闭以及定时时间可以配置详解...
一.序言: 最近项目需要用到定时任务,需要完成一个定时功能.经过了解,项目中目前实现定时任务,一般有三种选择,一是用Java自带的timer类.稍微看了一下,可以实现大部分的指定频率的任务的调度(ti ...
- java定时轮询_RxJava应用场景之轮询定时任务
Android开发中必不可少会遇到轮询或定时任务,在RxJava诞生之前,我们常常使用Handler+postDelay,或者Java中的Timer来实现,实际上RxJava也可以实现这类需求.下面, ...
最新文章
- Onenote 2010 多PC端笔记同步
- 防火墙术语详解(一)
- 以短带长进军网综,西瓜视频能否干过“优爱腾”?
- Testlink使用介绍
- JQuery的Ajax技术
- 适用于高级Java开发人员的十大书籍
- python 异步 生产者 消费者_python 线程通信 生产者与消费者
- Bash常用快捷键及其作用
- [转]Java 通过JDBC连接Mysql数据库的方法和实例【图文说明】
- CGLIB动态代理模式详解
- c#学习笔记之Application.DoEvents应用
- Oracle PL / SQL – INSTEAD OF触发器示例
- 新塘单片机烧写器_新唐单片机烧录工具-Nuvoton ICP Programming Tool下载v3.00.6909官方免费版-ucbug下载站...
- 多个vmdk合并成一个vmdk方法
- Android开发_ARN是什么
- C语言的数据类型大全,整型数据在内存中的存储方式
- 关于循环调用Variable RNN的reuse问题
- 探索者系列_百度百科
- Salt Pepper—The Art of Illustrating Texture
- 湖南工业大学教务系统爬虫(模拟登陆篇)
热门文章
- (原)JNI中env-GetByteArrayElements和AndroidBitmap_getInfo的冲突
- JavaScript判断是否是手机mobile登录
- ImportError: No module named pil
- 新的一年,,,新的生活
- 中国的人生路上是紧跟领导就会有回报
- 基于Vue+nodejs实现的前后端分离疫情防控系统
- java金额小写转大写(8.2)
- ubuntu 安装SSH并设置免密码登录
- [AHOI2005]约数研究
- 优化改良版:数组,List,等集合需要加逗号或其它符合转成字符串