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定时任务的常用实现的更多相关文章

  1. atititt.java定时任务框架选型Spring Quartz 注解总结

    atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz  (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...

  2. [转][JAVA]定时任务之-Quartz使用篇

    [BAT][JAVA]定时任务之-Quartz使用篇 定时任务之-Quartz使用篇 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与 ...

  3. Quartz实现JAVA定时任务的动态配置

    什么是动态配置定时任务? 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 定时任务实现方式千人千种,不过基础的无外乎 1.JDK 的Timer类 2. ...

  4. 基于java平台的常用资源整理

    这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...

  5. 这里整理了基于java平台的常用资源

    这里整理了基于java平台的常用资源 翻译 from :akullpp | awesome-java 大家一起学习,共同进步. 如果大家觉得有用,就mark一下,赞一下,或评论一下,让更多的人知道.t ...

  6. Java获取各种常用时间方法大全

    Java获取各种常用时间方法大全 package cc.javaweb.test; Java中文网,Java获取各种时间大全 import java.text.DateFormat; import j ...

  7. java定时任务

    java定时任务实现方法: public class TimingTask { private static int count = 0; private static SpiderService s ...

  8. Java定时任务器

    java定时任务,每天定时执行任务.以下是这个例子的全部代码. public class TimerManager { //时间间隔 private static final long PERIOD_ ...

  9. java中最常用jar包的用途说明

    java中最常用jar包的用途说明,适合初学者 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实 ...

随机推荐

  1. Fis3前端工程化之项目实战

    Fis3项目 项目目录结构: E:. │ .gitignore │ fis-conf.js │ index.html │ package.json │ README.md │ ├─material │ ...

  2. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  3. HTML DOM 介绍

    本篇主要介绍DOM内容.DOM 节点.节点属性以及获取HTML元素的方法. 目录 1. 介绍 DOM:介绍DOM,以及对DOM分类和功能的说明. 2. DOM 节点:介绍DOM节点分类和节点层次. 3 ...

  4. Content Security Policy 入门教程

    阮一峰文章:Content Security Policy 入门教程

  5. Hawk 4.4 执行器

    执行器是负责将Hawk的结果传送到外部环境的工具.你可以写入数据表,数据库,甚至执行某个特定的动作,或是生成文件等等. 在调试模式下,执行器都是不工作的.这是为了避免产生副作用.否则,每刷新一遍数据, ...

  6. 玩转spring boot——结合AngularJs和JDBC

    参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...

  7. PHP中PDO事务的使用方法

    事务 (Transaction) 是操作数据库中很重要的一个功能, 它可以让你预定一条, 或者一系列 SQL 语句, 然后一起执行. 在执行的过程中, 如果其中的某条执行失败, 可以回滚所有已更改的操 ...

  8. Java定时任务的常用实现

    Java的定时任务有以下几种常用的实现方式: 1)Timer 2)ScheduledThreadPoolExecutor 3)Spring中集成Cron Quartz 接下来依次介绍这几类具体实现的方 ...

  9. 微信小程序前端源码逻辑和工作流

    看完微信小程序的前端代码真的让我热血沸腾啊,代码逻辑和设计一目了然,没有多余的东西,真的是大道至简. 废话不多说,直接分析前端代码.个人观点,难免有疏漏,仅供参考. 文件基本结构: 先看入口app.j ...

  10. Tomcat常见问题及常用命令

    很长时间不用tomcat好多命令都忘记了,所以准备自己记录下来,以便参考.刚好也希望可以开始养成记博客的好习惯. 1.查看java的版本号 进入java的安装目录后,使用命令:java -versio ...