主要有以下三种实现方式:

JDK自带:JDK 自带的 Timer 以及 JDK1.5+ 新增的 ScheduledExecutorService;

Quartz:简单却强大的 JAVA 作业调度框架;

Spring3.0以后自带的task :可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多;

JDK 自带的定时器实现

Timer

这个类允许你调度一个java.util.TimerTask任务。主要有以下几个方法:

schedule(TimerTask task, long delay) 延迟 delay 毫秒执行

schedule(TimerTask task, Date time) 特定时间执行

schedule(TimerTask task, long delay, long period) 延迟 delay 执行并每隔 period 执行一次。用固定延迟调度。使用本方法时,在任务执行中的每一个延迟会传播到后续的任务的执行。

scheduleAtFixedRate(TimerTask task, long delay, long period) 延迟 delay 执行并固定速率 period 执行一次。用固定比率调度。使用本方法时,所有后续执行根据初始执行的时间进行调度,从而希望减小延迟。

ScheduledExecutorService

该定时任务接口,主要有以下几个方法

ScheduledFuture> schedule(Runnable command,long delay, TimeUnit unit);

ScheduledFutureschedule(Callablecallable,long delay, TimeUnit unit);

ScheduledFuture> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnitunit);

ScheduledFuture> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnitunit);

该接口的默认实现为 ScheduledThreadPoolExecutor 类,这个类继承了 ThreadPoolExecutor 类。线程池的使用使其比Timer更稳定。spring Task内部也是依靠它实现的。

Timer的缺陷

1、Timer在执行定时任务时只会创建一个线程,所以如果存在多个任务,且任务时间过长,超过了两个任务的间隔时间,后面的任务执行时间就被推迟。

packagecn.boomoom.service;importjava.util.Timer;importjava.util.TimerTask;public classTimerTest {private static longstart;public static voidmain(String[] args) {

TimerTask task1= newTimerTask() {

@Overridepublic voidrun() {

System.out.println("task1 invoked ! " + (System.currentTimeMillis() -start));try{

Thread.sleep(3000);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

};

TimerTask task2= newTimerTask() {

@Overridepublic voidrun() {

System.out.println("task2 invoked ! " + (System.currentTimeMillis() -start));

}

};

Timer timer= newTimer();

start=System.currentTimeMillis();

timer.schedule(task1,1000);

timer.schedule(task2,3000);

}

}

TimerTest

定义了两个任务,预计是第一个任务1s后执行,第二个任务3s后执行,但是看运行结果:

task1 invoked ! 1000task2 invoked! 4001

task2实际上是4后才执行,正因为Timer内部是一个线程,而任务1所需的时间超过了两个任务间的间隔导致。

packagecn.boomoom.service;importjava.util.TimerTask;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;public classScheduledExecutorServiceTest {private static longstart;public static voidmain(String[] args) {//使用工厂方法初始化一个ScheduledThreadPool

ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(2);

TimerTask task1= newTimerTask() {

@Overridepublic voidrun() {try{

System.out.println("task1 invoked ! " + (System.currentTimeMillis() -start));

Thread.sleep(3000);

}catch(Exception e) {

e.printStackTrace();

}

}

};

TimerTask task2= newTimerTask() {

@Overridepublic voidrun() {

System.out.println("task2 invoked ! " + (System.currentTimeMillis() -start));

}

};

start=System.currentTimeMillis();

newScheduledThreadPool.schedule(task1,1000, TimeUnit.MILLISECONDS);

newScheduledThreadPool.schedule(task2,3000, TimeUnit.MILLISECONDS);

}

}

ScheduledExecutorServiceTest

task1 invoked ! 1002task2 invoked! 3004

符合我们的预期结果。因为ScheduledThreadPool内部是个线程池,所以可以支持多个任务并发执行。

2、Timer当任务抛出异常时的缺陷。如果TimerTask抛出RuntimeException,Timer会停止所有任务的运行。

packagecn.boomoom.service;importjava.util.Date;importjava.util.Timer;importjava.util.TimerTask;public classTimerTest01 {public static voidmain(String[] args) {final TimerTask task1 = newTimerTask() {

@Overridepublic voidrun() {throw newRuntimeException();

}

};final TimerTask task2 = newTimerTask() {

@Overridepublic voidrun() {

System.out.println("task2 invoked!");

}

};

Timer timer= newTimer();

timer.schedule(task1,100);

timer.scheduleAtFixedRate(task2,new Date(), 1000);

}

}

TimerTest01

task2 invoked!Exception in thread"Timer-0"java.lang.RuntimeException

at cn.itcast.bos.service.TimerTest01$1.run(TimerTest01.java:14)

at java.util.TimerThread.mainLoop(Timer.java:555)

at java.util.TimerThread.run(Timer.java:505)

由于任务1的一次,任务2也停止运行了。

packagecn.boomoom.service;importjava.util.TimerTask;importjava.util.concurrent.Executors;importjava.util.concurrent.ScheduledExecutorService;importjava.util.concurrent.TimeUnit;public classScheduledExecutorServiceTest01 {public static voidmain(String[] args) {final TimerTask task1 = newTimerTask() {

@Overridepublic void run() { throw newRuntimeException();}

};final TimerTask task2 = newTimerTask() {

@Overridepublic void run() { System.out.println("task2 invoked!"); }

};

ScheduledExecutorService pool= Executors.newScheduledThreadPool(1);

pool.schedule(task1,100, TimeUnit.MILLISECONDS);

pool.scheduleAtFixedRate(task2,0, 1000, TimeUnit.MILLISECONDS);

}

}

ScheduledExecutorServiceTest01

task2 持续输出。ScheduledExecutorService 保证了,task1出现异常时,不影响task2的运行。

3、Timer执行周期任务时依赖系统时间,如果当前系统时间发生变化会出现一些执行上的变化,ScheduledExecutorService 基于时间的延迟,不会由于系统时间的改变发生执行变化。

Quartz 任务调度实现

quartz 的 java demo

http://www.quartz-scheduler.org/ 入门案例: http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html

1、导入maven坐标

4.0.0

cn.boomoom.maven

quartz_helloworld

0.0.1-SNAPSHOT

quartz_helloworld

org.quartz-scheduler

quartz

2.2.1

org.quartz-scheduler

quartz-jobs

2.2.1

org.slf4j

slf4j-log4j12

1.7.12

pom

2、quartz demo

packagecn.boomoom.service;import org.quartz.*;importorg.quartz.impl.StdSchedulerFactory;importjava.util.HashMap;importjava.util.Map;public classQuartzTest {public static void main(String[] args) throwsSchedulerException {

SchedulerFactory sf= newStdSchedulerFactory();

Scheduler scheduler=sf.getScheduler();

Map jobTriggerMap =jobAndTrigger();for (Map.Entryentry : jobTriggerMap.entrySet()) {

scheduler.scheduleJob(entry.getKey(), entry.getValue());

}

scheduler.start();

}private static MapjobAndTrigger() {

HashMap hashMap = new HashMap<>();

JobDetail job1= JobBuilder.newJob(HelloJob1.class).withIdentity("job1", "group1").build();

Trigger trigger1= TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()

.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

hashMap.put(job1, trigger1);

JobDetail job2= JobBuilder.newJob(HelloJob2.class).withIdentity("job2", "group1").build();

Trigger trigger2= TriggerBuilder.newTrigger().forJob("job2", "group1").startNow()

.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();

hashMap.put(job2, trigger2);

JobDetail job3= JobBuilder.newJob(HelloJob3.class).withIdentity("job3", "group1").build();

Trigger trigger3= TriggerBuilder.newTrigger().forJob("job3", "group1").startNow()

.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

hashMap.put(job3,trigger3);returnhashMap;

}

}

quartzTest

JobDetail、Trigger、Scheduler三个对象为Quartz主要对象。启动Trigger的定时方式由不同的ScheduleBuilder子类提供,如:SimpleScheduleBuilder、CronScheduleBuilder、DailyTimeIntervalScheduleBuilder、CalendarIntervalScheduleBuilder。

spring 集成 quartz

4.0.0

cn.boomoom.maven

quartz_spring

0.0.1-SNAPSHOT

war

quartz_spring

org.quartz-scheduler

quartz

2.2.1

org.quartz-scheduler

quartz-jobs

2.2.1

org.slf4j

slf4j-log4j12

1.7.12

org.springframework

spring-context

4.1.7.RELEASE

org.springframework

spring-context-support

4.1.7.RELEASE

org.springframework

spring-web

4.1.7.RELEASE

org.springframework

spring-tx

4.1.7.RELEASE

org.codehaus.mojo

tomcat-maven-plugin

1.1

9888

1、pom.xml

contextConfigLocation

classpath:applicationContext.xml

org.springframework.web.context.ContextLoaderListener

2、web.xml

packagecn.boomoom.job;importorg.quartz.JobExecutionContext;importorg.quartz.JobExecutionException;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.scheduling.quartz.QuartzJobBean;importcn.boomoom.service.HelloService;public class HelloJob extendsQuartzJobBean {

@AutowiredprivateHelloService helloService;

@Overrideprotected void executeInternal(JobExecutionContext context) throwsJobExecutionException {

helloService.sayHello();

}

}

HelloJob

packagecn.boomoom.service;importorg.springframework.stereotype.Service;

@Servicepublic classHelloService {public voidsayHello() {

System.out.println("hello,quartz service !");

}

}

HelloService

packagecn.boomoom.job;importorg.quartz.spi.TriggerFiredBundle;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.config.AutowireCapableBeanFactory;importorg.springframework.scheduling.quartz.AdaptableJobFactory;importorg.springframework.stereotype.Service;

@Service("jobFactory")public class JobFactory extendsAdaptableJobFactory {

@AutowiredprivateAutowireCapableBeanFactory capableBeanFactory;

@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throwsException {//调用父类的方法

Object jobInstance = super.createJobInstance(bundle);//进行注入

capableBeanFactory.autowireBean(jobInstance);returnjobInstance;

}

}

JobFactory

4、applicationContext.xml

spring提供了JobDetail、Trigger、Scheduler三个的factoryBean。

在 Job 中 spring 管理的 Bean 无法注入解决,需要在 Scheduler 中自定义 JobFactory。jobFactory 在创建job对象的时候,为其指定了 spring自动注入的属性,(类中的@Autowired)。

JobFactory 指定定义的时候,上面的方式有些时候不行,可以用下面的方式

importorg.quartz.spi.TriggerFiredBundle;importorg.springframework.beans.factory.config.AutowireCapableBeanFactory;importorg.springframework.context.ApplicationContext;importorg.springframework.context.ApplicationContextAware;importorg.springframework.scheduling.quartz.SpringBeanJobFactory;

@Service("jobFactory")public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implementsApplicationContextAware {private transientAutowireCapableBeanFactory beanFactory;

@Overridepublic void setApplicationContext(finalApplicationContext context) {

beanFactory=context.getAutowireCapableBeanFactory();

}

@Overrideprotected Object createJobInstance(final TriggerFiredBundle bundle) throwsException {final Object job = super.createJobInstance(bundle);

beanFactory.autowireBean(job);returnjob;

}

}

AutowiringSpringBeanJobFactory

JobFactory 参考1,参考2.     quartz定时任务实现只执行一次,SimpleTriggerFactoryBean

Spring 相关的任务调度

Spring 3.0+ 自带的任务调度实现,主要依靠TaskScheduler接口的几个实现类实现。

主要用法有以下三种:

配置文件实现

spring-schedule.xml

注解实现

spring-schedule.xml

// 启用注解

@Componentpublic classScheduleTask {//每隔5秒执行一次

@Scheduled(cron = "0/5 * * * * ?")public voidprintSay() {

System.out.println("每隔5秒执行一次:" + newDate());

}

}

代码动态添加

spring-schedule.xml

@Componentpublic classTest {

@AutowiredprivateThreadPoolTaskScheduler myScheduler;public voidaddJob(){

myScheduler.schedule(newRunnable() {

@Overridepublic voidrun() {

System.out.println(Thread.currentThread().getName()+ " run ");

}

} ,new CronTrigger("0/5 * * * * ? ")); //每5秒执行一次

}

}

java 定时任务哪个好_Java定时任务相关推荐

  1. java实现周期任务_java定时任务的实现方式

    本文列举常见的java定时任务实现方式,并做一定比较. 1. 循环内部sleep实现周期执行 创建一个thread,run() while循环里sleep()来实现周期性执行; 简单粗暴,作为一个初学 ...

  2. java文件定时读写_java定时任务及日志的使用

    需要引入日志的两个架包: log4j.jar和commons-logging.jar package com.lzl; import java.util.TimerTask; import org.a ...

  3. java一定时间间隔的定时任务_Java 定时任务---Timer

    本文来自我一个朋友的个人博客(希望各位以后多多支持):https://www.liupeng.mobi/archives/777 一.Timer类 在java中一个完整的定时任务需要由Timer和Ti ...

  4. Java使用quartz实现任务调度定时任务

    1.添加quartz依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter ...

  5. java分布式定时_分布式定时任务程序

    分布式定时任务程序 介绍 基于zookeeper实现的分布式定时任务程序. 软件架构 包含: 1.zookeeper 2.quartz 3.curator 4.rabbitmq 5.springboo ...

  6. Java的定时器Timer和定时任务TimerTask应用以及原理简析

    记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析.在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.u ...

  7. 定时任务:创建静态定时任务、动态定时任务

    定时任务有三种实现 1 jdk自带的定时任务 2 Quartz插件实现的定时任务,需要引入额外的包 3 SpringTask定时调度,是对jdk的再一次封装,不用引入其他包了,用spring的包就自带 ...

  8. java签到 表设计_java springboot 7天签到功能设计 数据库表设计 加代码

    实现一个类似于这样的签到功能 (参考的百度网盘签到页面) 数据表是一个用户只有一条签到记录的设计, 没有使用签到一次表中加一条数据, 那样的话数据太多了 表结构: CREATE TABLE `sign ...

  9. php添加linux定时任务,PHP与Linux定时任务

    定时任务在实际开发中用到是非常多的,这里也简单说说PHP怎么执行定时任务.我们都知道PHP是一门解释性语言,当我们在浏览器中输入某个URL时,我们才能去执行PHP,但是如果不访问URL呢,怎么让PHP ...

最新文章

  1. 数组--存储地址的计算
  2. Python 计算机视觉(五)—— OpenCV 进行图像几何变换
  3. c++ 异步下获取线程执行结果_这份阿里技术官强推的java线程池笔记,建议你看一下
  4. omnipay支付--支付宝支付
  5. HTML5 Shiv #8211; 让该死的IE系列支持HTML5吧
  6. Office Web Apps安装部署(一)
  7. Linux内存管理slub分配器
  8. vs 2017 专业版 密钥
  9. android炫酷动画源码,QQ菜单、瀑布流、二维码源码
  10. SD卡格式化造成数据丢失的恢复方法
  11. 没有计算机的一天英语作文带翻译,美好的一天糟糕的一天英语作文带翻译
  12. 【场景实现】Vue+element如何让帖子评论带上emoji,这个需求让我在富文本Quill开始了踩坑连连看
  13. 远程连接桌面计算机的凭据,凭据的远程桌面连接 - Windows Server | Microsoft Docs
  14. 亦舒的话,我的感触...
  15. 【Android常识】Android之父Andy Rubin:被乔布斯羡慕嫉妒的天才
  16. oracle 使用,Oracle 使用
  17. 手机照片压缩的快捷方法
  18. 如何让谷歌google、百度baidu和雅虎yahoo收录我的网站
  19. 微信公众号:微信H5页面JSAPI充值
  20. 火箭还是飞机?——DevOps 的两种模式

热门文章

  1. 程序员生存定律--定律的概要
  2. c语言数组元素下标下限1,C语言中,数组元素的下标下限为
  3. 甘肃临夏扶贫贷款助贫困农户“无牛羊不成家”
  4. ART与Dalvik哪个好 ART模式和Dalvik模式区别对比
  5. [转载]游击队员之歌
  6. 经典算法21--十字链表
  7. iPhone 6首日订单量创纪录 苹果在线商店宕机
  8. 华为抓截屏_华为手机有6种截屏方法,你都知道几种?
  9. 320. 能量项链 (区间dp)
  10. 3行python代码翻译70种语言,这个OCR神奇太赞了