java 定时任务实现方式
一、JDK自带定时任务
1、Timer
java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
public class TestTimer {public static void main(String[] args) {TimerTask timerTask = new TimerTask() {@Overridepublic void run() {System.out.println("task run:"+ new Date());}};Timer timer = new Timer();//安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次timer.schedule(timerTask,10,3000);}
}
2、ScheduledExecutorService(JDK)
jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
public class MyScheduledExecutorService { public static void main(String[] args) { // 创建任务队列 10 为线程数量 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10); // 执行任务 scheduledExecutorService.scheduleAtFixedRate(() -> { System.out.println("打印当前时间:" + new Date()); }, 1, 3, TimeUnit.SECONDS); // 1s 后开始执行,每 3s 执行一次 }
}
二、spring 支持定时任务
1、Spring Task
Spring3.0系列框架中Spring Framework自带的定时任务,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId>
</dependency>
@EnableScheduling
@SpringBootApplication
public class Application {public static void main(String[] args) {new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);}
}
sue.spring.task.cron=*/10 * * * * ?
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component // 把此类托管给 Spring,不能省略
public class TaskUtils { @Scheduled(cron = "${sue.spring.task.cron}")public void fun() {System.out.println("doSomething");}// 添加定时任务 @Scheduled(cron = "30 40 23 0 0 5") // cron表达式:每周一 23:40:30 执行 public void doTask(){ System.out.println("我是定时任务~"); }/**fixedRate:上一次开始执行时间点之后5秒再执行*/@Scheduled(fixedRate = 5000)public void run1() throws InterruptedException {Thread.sleep(6000);System.out.println(Thread.currentThread().getName()+"=====>>>>>使用fixedRate {}"+(System.currentTimeMillis()/1000));}/**fixedDelay:上一次执行完毕时间点之后5秒再执行*/@Scheduled(fixedDelay = 5000)public void run2() throws InterruptedException {Thread.sleep(7000);System.out.println(Thread.currentThread().getName()+"=====>>>>>使用fixedDelay {}"+(System.currentTimeMillis()/1000));}/**第一次延迟2秒后执行,之后按fixedDelay的规则每5秒执行一次*/@Scheduled(initialDelay = 2000, fixedDelay = 5000)public void run3(){System.out.println(Thread.currentThread().getName()+"=====>>>>>使用initialDelay {}"+(System.currentTimeMillis()/1000));}}
多线程执行(在类或方法上加@Async)
@Configuration
@EnableAsync //开启异步事件的支持
public class AsyncConfig {/*此处成员变量应该使用@Value从配置中读取*/private int corePoolSize = 10;private int maxPoolSize = 200;private int queueCapacity = 10;@Beanpublic Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(corePoolSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(queueCapacity);executor.initialize();return executor;}
}
cron常用表达式
0 0 0 1 * ?
每月1号零点执行0 0 2 * * ?
每天凌晨2点执行0 0 2 * * ?
每天凌晨2点执行0 0/5 11 * * ?
每天11点-11点55分,每隔5分钟执行一次0 0 18 ? * WED
每周三下午6点执行- 每隔5秒执行一次:*/5 ** ?
- 每隔1分钟执行一次:0 */1 *?
- 0/2 * * * * ? 表示每2秒 执行任务
- 0 0/2 * * * ? 表示每2分钟 执行任务
- 0 0 2 1 * ? 表示在每月的1日的凌晨2点调整任务
- 0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
- 0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作
- 0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
- 0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
- 0 0 12 ? * WED 表示每个星期三中午12点
- 0 0 12 * * ? 每天中午12点触发
- 0 15 10 ? * * 每天上午10:15触发
- 0 15 10 * * ? 每天上午10:15触发
- 0 15 10 * * ? 每天上午10:15触发
- 0 15 10 * * ? 2005 2005年的每天上午10:15触发
- 0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
- 0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
- 0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
- 0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
- 0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
- 0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
- 0 15 10 15 * ? 每月15日上午10:15触发
- 0 15 10 L * ? 每月最后一日的上午10:15触发
- 0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
- 0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
- 0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
2、Spring Quartz
quartz主要接口:
Scheduler
代表调度容器,一个调度容器中可以注册多个JobDetail和Trigger。Job
代表工作,即要执行的具体内容。JobDetail
代表具体的可执行的调度程序,Job是这个可执行程调度程序所要执行的内容。JobBuilder
用于定义或构建JobDetail实例。Trigger
代表调度触发器,决定什么时候去调。TriggerBuilder
用于定义或构建触发器。JobStore
用于存储作业和任务调度期间的状态。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
- 定时任务执行类继承
QuartzJobBean
public class QuartzTestJob extends QuartzJobBean {@Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {String userName = (String) context.getJobDetail().getJobDataMap().get("userName");System.out.println("userName:" + userName);}
}
- 创建调度程序
JobDetail
和调度器Trigger
@Configuration
public class QuartzConfig {@Value("${sue.spring.quartz.cron}")private String testCron;/*** 创建定时任务*/@Beanpublic JobDetail quartzTestDetail() {JobDetail jobDetail = JobBuilder.newJob(QuartzTestJob.class).withIdentity("quartzTestDetail", "QUARTZ_TEST").usingJobData("userName", "susan").storeDurably().build();return jobDetail;}/*** 创建触发器*/@Beanpublic Trigger quartzTestJobTrigger() {//每隔5秒执行一次CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(testCron);//创建触发器Trigger trigger = TriggerBuilder.newTrigger().forJob(quartzTestDetail()).withIdentity("quartzTestJobTrigger", "QUARTZ_TEST_JOB_TRIGGER").withSchedule(cronScheduleBuilder).build();return trigger;}
}
sue.spring.quartz.cron=*/5 * * * * ?
优点:默认是多线程异步执行,单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度,多个任务之间互不影响。支持复杂的
cron
表达式,它能被集群实例化,支持分布式部署。缺点:相对于spring task实现定时任务成本更高,需要手动配置
QuartzJobBean
、JobDetail
和Trigger
等。需要引入了第三方的quartz
包,有一定的学习成本。不支持并行调度,不支持失败处理策略和动态分片的策略等。
三、分布式定时任务
1、xxl-job
xxl-job
框架对quartz
进行了扩展,使用mysql
数据库存储数据,并且内置jetty作为RPC
服务调用。
有界面维护定时任务和触发规则,非常容易管理。
能动态启动或停止任务
支持弹性扩容缩容
支持任务失败报警
支持动态分片
支持故障转移
Rolling实时日志
支持用户和权限管理
管理界面:
整体架构:
quartz架构图 :
1.1、 部署xxl-job-admin
https://www.jianshu.com/p/fa7186bea84b
1.2、 xxl-job使用
- pom.xml文件中引入
xxl-job
相关依赖
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId>
</dependency>
applicationContext.properties
文件中配置参数
#调度中心部署跟地址
xxl.job.admin.address: http://localhost:8088/xxl-job-admin/
xxl.job.executor.appname: xxl-job-executor-sample
xxl.job.executor.port: 8888
xxl.job.executor.logpath: /data/applogs/xxl-job/
- 创建HelloJobHandler类继承
IJobHandler
类
package com.tp.athena.jobhandler;import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.stereotype.Component;import javax.sound.midi.Soundbank;
import java.util.concurrent.TimeUnit;/*** 任务Handler示例(Bean模式)* <p>* 开发步骤:* 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”;* 2、注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例;* 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,注解value值对应的是调度中心新建任务的JobHandler属性的值。* 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;** @author xuxueli 2015-12-19 19:43:36*/
@JobHandler(value = "demoJobHandler")
@Component
public class DemoJobHandler extends IJobHandler {@Overridepublic ReturnT<String> execute(String param) throws Exception {System.out.println("XXL-JOB Hello World");return SUCCESS;}
}
使用xxl-job
的优缺点:
优点:有界面管理定时任务,支持弹性扩容缩容、动态分片、故障转移、失败报警等功能。它的功能非常强大,很多大厂在用,可以满足绝大多数业务场景。
缺点:和
quartz
一样,通过数据库分布式锁,来控制任务不能重复执行。在任务非常多的情况下,有一些性能问题。
2、elastic-job
elastic-job
是当当网开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分布式协调,实现任务高可用以及分片。它是专门为高并发和复杂业务场景开发。
elastic-job
目前是apache
的shardingsphere
项目下的一个子项目,官网地址:http://shardingsphere.apache.org/elasticjob/。
elastic-job
在2.x之后,出了两个产品线:Elastic-Job-Lite
和Elastic-Job-Cloud
,而我们一般使用Elastic-Job-Lite就能够满足需求。Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务,外部仅依赖于Zookeeper。
分布式调度协调
弹性扩容缩容
失效转移
错过执行作业重触发
作业分片一致性,保证同一分片在分布式环境中仅一个执行实例
自诊断并修复分布式不稳定造成的问题
支持并行调度
整体架构:
- pom.xml文件中引入
elastic-job
相关依赖
<dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-core</artifactId>
</dependency>
<dependency><groupId>com.dangdang</groupId><artifactId>elastic-job-lite-spring</artifactId>
</dependency>
- 增加ZKConfig类,配置
zookeeper
@Configuration
@ConditionalOnExpression("'${zk.serverList}'.length() > 0")
public class ZKConfig {@Beanpublic ZookeeperRegistryCenter registry(@Value("${zk.serverList}") String serverList,@Value("${zk.namespace}") String namespace) {return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList, namespace));}}
- 定义一个类实现
SimpleJob
接口
public class TestJob implements SimpleJob {@Overridepublic void execute(ShardingContext shardingContext){System.out.println("ShardingTotalCount:"+shardingContext.getShardingTotalCount());System.out.println("ShardingItem:"+shardingContext.getShardingItem());}
}
- 增加JobConfig配置任务
cron:cron表达式,定义触发规则。
shardingTotalCount:定义作业分片总数
shardingItemParameters:定义分配项参数,一般用分片序列号和参数用等号分隔,多个键值对用逗号分隔,分片序列号从0开始,不可大于或等于作业分片总数。
jobParameters:作业自定义参数
@Configuration
public class JobConfig {@Value("${sue.spring.elatisc.cron}")private String testCron;@Value("${sue.spring.elatisc.itemParameters}")private String shardingItemParameters;@Value("${sue.spring.elatisc.jobParameters}")private String jobParameters =;@Value("${sue.spring.elatisc.shardingTotalCount}")private int shardingTotalCount;@Autowiredprivate ZookeeperRegistryCenter registryCenter;@Beanpublic SimpleJob testJob() {return new TestJob();}@Beanpublic JobScheduler simpleJobScheduler(final SimpleJob simpleJob) {return new SpringJobScheduler(simpleJob, registryCenter, getConfiguration(simpleJob.getClass(),cron, shardingTotalCount, shardingItemParameters, jobParameters));}private geConfiguration getConfiguration(Class<? extends SimpleJob> jobClass,String cron,int shardingTotalCount,String shardingItemParameters,String jobParameters) {JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(jobClass.getName(), testCron, shardingTotalCount).shardingItemParameters(shardingItemParameters).jobParameter(jobParameters).build();SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, jobClass.getCanonicalName());LiteJobConfiguration jobConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).overwrite(true).build();return jobConfig;}
}
applicationContext.properties
文件中配置参数
spring.application.name=elasticjobDemo
zk.serverList=localhost:2181
zk.namespace=elasticjobDemo
sue.spring.elatisc.cron=0/5 * * * * ?
sue.spring.elatisc.itemParameters=0=A,1=B,2=C,3=D
sue.spring.elatisc.jobParameters=test
sue.spring.elatisc.shardingTotalCount=4
使用elastic-job
的优缺点:
优点:支持分布式调度协调,支持分片,适合高并发,和一些业务相对来说较复杂的场景。
缺点:需要依赖于zookeeper,实现定时任务相对于
xxl-job
要复杂一些,要对分片规则非常熟悉。
java 定时任务实现方式相关推荐
- Spring Boot 整合 Quartz 实现 Java 定时任务的动态配置
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看 ...
- java定时任务框架elasticjob详解
这篇文章主要介绍了java定时任务框架elasticjob详解,Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.该项目基于成熟的开源产品Quartz和Zo ...
- Springboot2 Quartz实现JAVA定时任务的动态配置
动态配置Quartz.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 文章目录 一.需求背景 1. 问题现象 2. 问题分析 3. 解决方案 二.需求背景 2.1. maven依 ...
- Java定时任务(一) Timer及TimerTask的案例解析及源码分析
Java定时任务(一) Timer及TimerTask的案例解析及源码分析 一.概述: 定时任务这个概念在Java的学习以及项目的开发中并不陌生,应用场景也是多种多样.比如我们会注意到12306网站 ...
- Java定时任务技术分析
<从零打造项目>系列文章 工具 比MyBatis Generator更强大的代码生成器 ORM框架选型 SpringBoot项目基础设施搭建 SpringBoot集成Mybatis项目实操 ...
- Java 定时任务详解
文章目录 单机定时任务技术选型 Timer ScheduledExecutorService Spring Task 时间轮 分布式定时任务技术选型 Quartz Elastic-Job XXL-JO ...
- JAVA定时任务怎么实现
序章:定时任务实现方式 当下,java编码过程中,实现定时任务的方式主要以以下两种为主 spring框架的@Scheduled quzrtz框架 网络上关于这两种框架的实践和配置相关的教程很多,这里不 ...
- SpringBoot下使用定时任务的方式全揭秘
本文旨在用通俗的语言讲述枯燥的知识 定时任务作为一种系统调度工具,在一些需要有定时作业的系统中应用广泛,如每逢某个时间点统计数据.在将来某个时刻执行某些动作-定时任务在主流开发语言均提供相应的API供 ...
- JAVA定时任务-发送邮箱提醒-王大师王文峰开发(已上线完成)】
本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,<Java王大师王天师>作者 公众号:山峯草堂,非技术多篇文章,专注于天道酬勤的 Java 开发问题.中国国学.传统文化和代 ...
最新文章
- STM32-USART控制led和蜂鸣器
- 一个数里有那些约数用c++怎么做_嵌入式就业的那些事~
- 弯道极限超车、击败人类顶级玩家,索尼AI赛车手登上Nature封面
- python 的日志logging模块学习
- @ImportResource
- 互联网1分钟 | 1011
- C语言素数分解prime factoriziation算法(附完整源码)
- 构造、拷贝构造、赋值、析构
- IDEA clone项目
- idea license 20200104
- 从单张图重建三维人体模型综述(六)
- iOS5编程--官方例子代码的研究--2.UICatalog-6
- python-map()/reduce()/filter()/sorted()/排列组合
- wireshark分析PS流格式解析详解
- Java程序员“金三银四“就一定要出去面试吗?
- 天梯赛省赛选拔赛复盘
- 一键解锁,宿舍管理隐藏技能
- 计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序
- 【C语言算法】归并排序
- 开发简单Android聊天软件(7)
热门文章
- 2022CCPC网络预选赛c题Problem C. Guess
- 百度地图api周边搜索功能,用单选按钮切换搜索类型
- 谈一谈,自身对技术经理这个职位的理解吧
- 黑盒子法探索人脑逻辑模型备忘录
- 计算机网络 层次路由,计算机网络-网络层(5)层次路由
- java 通过 ip地址 找到 打印机_有没有办法使用java套接字程序找到打印机状态?...
- HDTV 之-HDMI HPD
- (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
- Flex布局和gird布局
- C# 将dataTable中的数据导出到excel表中