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在执行定时任务时只会创建一个线程,所以如果存在多个任务,且任务时间过长,超过了两个任务的间隔时间,后面的任务执行时间就被推迟。
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定时任务相关推荐
- java实现周期任务_java定时任务的实现方式
本文列举常见的java定时任务实现方式,并做一定比较. 1. 循环内部sleep实现周期执行 创建一个thread,run() while循环里sleep()来实现周期性执行; 简单粗暴,作为一个初学 ...
- java文件定时读写_java定时任务及日志的使用
需要引入日志的两个架包: log4j.jar和commons-logging.jar package com.lzl; import java.util.TimerTask; import org.a ...
- java一定时间间隔的定时任务_Java 定时任务---Timer
本文来自我一个朋友的个人博客(希望各位以后多多支持):https://www.liupeng.mobi/archives/777 一.Timer类 在java中一个完整的定时任务需要由Timer和Ti ...
- Java使用quartz实现任务调度定时任务
1.添加quartz依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter ...
- java分布式定时_分布式定时任务程序
分布式定时任务程序 介绍 基于zookeeper实现的分布式定时任务程序. 软件架构 包含: 1.zookeeper 2.quartz 3.curator 4.rabbitmq 5.springboo ...
- Java的定时器Timer和定时任务TimerTask应用以及原理简析
记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析.在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.u ...
- 定时任务:创建静态定时任务、动态定时任务
定时任务有三种实现 1 jdk自带的定时任务 2 Quartz插件实现的定时任务,需要引入额外的包 3 SpringTask定时调度,是对jdk的再一次封装,不用引入其他包了,用spring的包就自带 ...
- java签到 表设计_java springboot 7天签到功能设计 数据库表设计 加代码
实现一个类似于这样的签到功能 (参考的百度网盘签到页面) 数据表是一个用户只有一条签到记录的设计, 没有使用签到一次表中加一条数据, 那样的话数据太多了 表结构: CREATE TABLE `sign ...
- php添加linux定时任务,PHP与Linux定时任务
定时任务在实际开发中用到是非常多的,这里也简单说说PHP怎么执行定时任务.我们都知道PHP是一门解释性语言,当我们在浏览器中输入某个URL时,我们才能去执行PHP,但是如果不访问URL呢,怎么让PHP ...
最新文章
- 数组--存储地址的计算
- Python 计算机视觉(五)—— OpenCV 进行图像几何变换
- c++ 异步下获取线程执行结果_这份阿里技术官强推的java线程池笔记,建议你看一下
- omnipay支付--支付宝支付
- HTML5 Shiv #8211; 让该死的IE系列支持HTML5吧
- Office Web Apps安装部署(一)
- Linux内存管理slub分配器
- vs 2017 专业版 密钥
- android炫酷动画源码,QQ菜单、瀑布流、二维码源码
- SD卡格式化造成数据丢失的恢复方法
- 没有计算机的一天英语作文带翻译,美好的一天糟糕的一天英语作文带翻译
- 【场景实现】Vue+element如何让帖子评论带上emoji,这个需求让我在富文本Quill开始了踩坑连连看
- 远程连接桌面计算机的凭据,凭据的远程桌面连接 - Windows Server | Microsoft Docs
- 亦舒的话,我的感触...
- 【Android常识】Android之父Andy Rubin:被乔布斯羡慕嫉妒的天才
- oracle 使用,Oracle 使用
- 手机照片压缩的快捷方法
- 如何让谷歌google、百度baidu和雅虎yahoo收录我的网站
- 微信公众号:微信H5页面JSAPI充值
- 火箭还是飞机?——DevOps 的两种模式