Java定时任务的常用实现
Java的定时任务有以下几种常用的实现方式:
1)Timer
2)ScheduledThreadPoolExecutor
3)Spring中集成Cron Quartz
接下来依次介绍这几类具体实现的方式
1. Timer
利用Java自带的定时类java.util.Timer以及java.util.TimerTask共同实现多任务的定时触发与周期性执行,主要包含以下两个方法:
void schedule(TimerTask task, long delay, long period);
void scheduleAtFixedRate(TimerTask task, long delay, long period);
其中delay表示第一次执行的延迟(毫秒),period表示周期性执行的时间间隔(毫秒)。其中,需要特别注意的是这两个方法中的period都为该任务后一次执行的起始时间与前一次执行的起始时间只差,但schedule()方法该任务后一次执行的起始时间并非固定,而是取决于前一次任务的执行耗时(如果该耗时大于period,那后一次执行必须等待前一次执行完毕后立即执行,所以并不是严格的时间间隔);反观scheduleAtFixedRate()方法后一次执行则不受前一次执行耗时的影响,因此如果前一次执行较慢,可能出现两次执行并发执行的场景。
Timer典型的用法如下:
long delay = 1000L;
long period = 5000L;
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
}
}, delay, period);
Timer的实现过程需要依赖内部的任务队列TaskQueue与任务线程TimerThread,其中TaskQueue以最小堆的方式实现任务优先队列,而TimerThread为单线程执行线程。因此存在的一个问题就是一旦该单线程在执行某个任务时由于某些原因hang住,那后续的其余任务执行都会受到影响。
2. ScheduledThreadPoolExecutor
继承自ThreadPoolExecutor的java.util.concurrent.ScheduledThreadPoolExecutor也可以实现多任务的定时触发与周期性执行,并且通常是多线程执行(线程池的形式),主要包含以下两个方法:
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
其中,scheduleAtFixedRate()方法与Timer的schedule()方法是类似的,后一次执行受到前一次执行耗时的影响;但scheduleWithFixedDelay()方法中的period则表示该任务后一次执行的起始时间与前一次执行的结束时间只差,这点与Timer的scheduleAtFixedRate()方法不同。
既然ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,那构成线程池核心的要素仍然是一样的:
- int corePoolSize
- int maximumPoolSize
- long keepAliveTime
- BlockingQueue<Runnable> workQueue
- ThreadFactory threadFactory
- RejectedExecutionHandler handler
但有所不同的是,ScheduledThreadPoolExecutor允许自定义的参数仅包括corePoolSize、threadFactory和handler,而maximumPoolSize恒为Integer.MAX_VALUE,keepAliveTime恒为0,workQueue恒为new DelayedWorkQueue(),这就意味着工作队列其实是无界的,且maximumPoolSize是无用的,corePoolSize就是工作线程的总个数(不会再增加)。
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
由于ScheduledThreadPoolExecutor是多个线程组成的线程池,因此不容易出现由于某个耗时任务导致其余定时任务难以分配线程无法执行的情况,因此更建议使用ScheduledThreadPoolExecutor取代Timer。
3. Cron Quartz
如果是一个Spring项目,则不妨使用Cron Quartz来更为灵活地制定定时任务,首先需要在pom.xml中增加对其的依赖配置,如下:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
随后,编写一个XML配置文件(如time-task.xml),用于指定定时任务类和相应的触发时间等(配置的方法不止一种,但本质上大同小异,这里仅提供一种作为参考):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 后台流量统计定时任务配置 -->
<bean id="flowDaemon" class="com.xxx.stats.service.impl.GetFlowDaemon">
</bean>
<bean id="FlowDaemonDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--false表示等上一个任务执行完后再开启新的任务 -->
<property name="concurrent" value="false"/>
<property name="targetObject" ref="flowDaemon"/>
<property name="targetMethod" value="execute"/>
</bean> <!-- 调度触发器 -->
<bean id="FlowDaemonTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="FlowDaemonDetail"/>
<property name="cronExpression" value="0 30 0/1 * * ?"/>
</bean> <!-- 调度工厂 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="FlowDaemonTrigger"/>
</list>
</property>
</bean>
</beans>
这里假设定时任务为一个后台流量统计任务,每小时30分触发一次(配置在cronExpression中),执行的方法为com.xxx.stats.service.impl.GetFlowDaemon.execute(),且如果前一个任务延后,后一个任务也顺延(即不会并发执行)。这种配置的好处就在于所有的配置全部在XML文件中完成,而无需对Java代码有任何的改动。
类似于0 30 0/1 * * ?的定时任务时间的设定写法是非常丰富的,支持多样化的需求,详见Cron Quartz官方教程。
REFERENCES
[1] https://my.oschina.net/pingpangkuangmo/blog/745704
[2] http://www.cnblogs.com/hanganglin/articles/3526240.html
[3] http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
[4] https://my.oschina.net/u/2851681/blog/744997
[5] http://www.cnblogs.com/obullxl/archive/2011/07/10/spring-quartz-cron-integration.html
为尊重原创成果,如需转载烦请注明本文出处:http://www.cnblogs.com/fernandolee24/p/5877516.html,特此感谢
Java定时任务的常用实现的更多相关文章
- atititt.java定时任务框架选型Spring Quartz 注解总结
atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...
- [转][JAVA]定时任务之-Quartz使用篇
[BAT][JAVA]定时任务之-Quartz使用篇 定时任务之-Quartz使用篇 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与 ...
- Quartz实现JAVA定时任务的动态配置
什么是动态配置定时任务? 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 定时任务实现方式千人千种,不过基础的无外乎 1.JDK 的Timer类 2. ...
- 基于java平台的常用资源整理
这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...
- 这里整理了基于java平台的常用资源
这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...
- Java获取各种常用时间方法大全
Java获取各种常用时间方法大全 package cc.javaweb.test; Java中文网,Java获取各种时间大全 import java.text.DateFormat; import j ...
- java定时任务
java定时任务实现方法: public class TimingTask { private static int count = 0; private static SpiderService s ...
- Java定时任务器
java定时任务,每天定时执行任务.以下是这个例子的全部代码. public class TimerManager { //时间间隔 private static final long PERIOD_ ...
- java中最常用jar包的用途说明
java中最常用jar包的用途说明,适合初学者 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实 ...
随机推荐
- Hibernatel框架关联映射
Hibernatel框架关联映射 Hibernate程序执行流程: 1.集合映射 需求:网络购物时,用户购买商品,填写地址 每个用户会有不确定的地址数目,或者只有一个或者有很多.这个时候不能把每条地址 ...
- C语言 · 字符转对比
问题描述 给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等.比如 Beijing 和 Hebei 2:两个字符串不仅长度相 ...
- [C#] 了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数
了解过入口函数 Main() 吗?带你用批处理玩转 Main 函数 目录 简介 特点 方法的参数 方法的返回值 与批处理交互的一个示例 简介 我们知道,新建一个控制台应用程序的时候,IDE 会同时创建 ...
- dubbox微服务实例及引发的“血案”
Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 主要核心部件: Remoting: 网络通信框架 ...
- 如何利用ansible callback插件对执行结果进行解析
最近在写一个批量巡检工具,利用ansible将脚本推到各个机器上执行,然后将执行的结果以json格式返回来. 如下所示: # ansible node2 -m script -a /root/pyth ...
- ASP.NET Core 中文文档目录
翻译计划 五月中旬 .NET Core RC2 如期发布,我们遂决定翻译 ASP.NET Core 文档.我们在 何镇汐先生. 悲梦先生. 张仁建先生和 雷欧纳德先生的群中发布了翻译计划招募信息,并召 ...
- [LintCode]——目录
Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...
- css样式之border-radius
border-radius 属性设置边框的园角 可能的值:像素,百分比 扩展延伸 html代码 <div></div> css代码 div { height: 200px; w ...
- 设计模式之工厂模式VS抽象工厂
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- php+websocket搭建简易聊天室实践
1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...