java 定时任务哪个好_Java定时任务

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

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在执行定时任务时只会创建一个线程,所以如果存在多个任务,且任务时间过长,超过了两个任务的间隔时间,后面的任务执行时间就被推迟。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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所需的时间超过了两个任务间的间隔导致。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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会停止所有任务的运行。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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也停止运行了。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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坐标

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

contextConfigLocation

classpath:applicationContext.xml

org.springframework.web.context.ContextLoaderListener

2、web.xml

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

@Servicepublic classHelloService {public voidsayHello() {

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

}

}

HelloService

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

4、applicationContext.xml

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

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

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

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

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秒执行一次

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值