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. 游戏服务器菜鸟之C#初探一游戏服务

    本人80后程序猿一枚,原来搞过C++/Java/C#,因为工作原因最后选择一直从事C#开发,因为读书时候对游戏一直比较感兴趣,机缘巧合公司做一个手游的项目,我就开始游戏服务器的折腾之旅. 游戏的构架是 ...

  2. C#多线程之基础篇3

    在上一篇C#多线程之基础篇2中,我们主要讲述了确定线程的状态.线程优先级.前台线程和后台线程以及向线程传递参数的知识,在这一篇中我们将讲述如何使用C#的lock关键字锁定线程.使用Monitor锁定线 ...

  3. CRL快速开发框架系列教程六(分布式缓存解决方案)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. vue.js初探

    前言 入手2016最火前端框架之一vue.js.大概从网上找了些资料看了下vue.js,从网上的资料来看只能惊叹其发展速度太快,让我意外的是其作者是华人的前提下作品这么受欢迎. 网上的博客和教程各种组 ...

  5. ASP.NET Core 中文文档 第四章 MVC(3.7 )局部视图(partial)

    原文:Partial Views 作者:Steve Smith 翻译:张海龙(jiechen).刘怡(AlexLEWIS) 校对:许登洋(Seay).何镇汐.魏美娟(初见) ASP.NET Core ...

  6. C语言中如何判断文件是否存在

    方法一:access函数判断文件夹或者文件是否存在 函数原型: int access(const char *filename, int mode); 所属头文件:io.h filename:可以填写 ...

  7. ViewController respondsToSelector 错误的解决方法

    原因解析:(来自别人博客分析)某个公共类或系统提供的控件,存在delegate方法,当创建此公共控件的容器类已经销毁,而这个控件对应的服务是在其它run loop中进行的,控件销毁或者需要进行状态通知 ...

  8. SqlServer简单数据分页

    手边开发的后端项目一直以来都用的.NET MVC框架,访问数据库使用其自带的EF CodeFirst模式,写存储过程的能力都快退化了 闲来无事,自己写了条分页存储过程,网上类似的文章多的是,这里只列了 ...

  9. 在VMware上安装CentOS -7

    1.下载好VMware 2.准备好CentOS的镜像文件 3.打开VMware创建新的虚拟机 选择自定义高级后按下一步 继续下一步 选择稍后安装操作系统 客户机操作系统选择Linux,版本选择Cent ...

  10. 解决Ubuntu Kylin 1610安装ANSYS17.2的NVIDIA显卡驱动问题

    Ubuntu Kylin 1610在安装完毕后,会自动安装显卡驱动,对于一般的图形图像使用来说自然不会有太大的问题,但是对于ANSYS17.2的一些模块,还是会出现问题.一个比较常见的问题就是Open ...