一、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实现定时任务成本更高,需要手动配置QuartzJobBeanJobDetailTrigger等。需要引入了第三方的quartz包,有一定的学习成本。不支持并行调度,不支持失败处理策略和动态分片的策略等。

三、分布式定时任务

1、xxl-job

xxl-job框架对quartz进行了扩展,使用mysql数据库存储数据,并且内置jetty作为RPC服务调用。

  1. 有界面维护定时任务和触发规则,非常容易管理。

  2. 能动态启动或停止任务

  3. 支持弹性扩容缩容

  4. 支持任务失败报警

  5. 支持动态分片

  6. 支持故障转移

  7. Rolling实时日志

  8. 支持用户和权限管理

管理界面:

 整体架构:

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目前是apacheshardingsphere项目下的一个子项目,官网地址:http://shardingsphere.apache.org/elasticjob/。

elastic-job在2.x之后,出了两个产品线:Elastic-Job-LiteElastic-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 定时任务实现方式相关推荐

  1. Spring Boot 整合 Quartz 实现 Java 定时任务的动态配置

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 首先说下这次主题,动态配置.没接触过定时任务的同学可以先看 ...

  2. java定时任务框架elasticjob详解

    这篇文章主要介绍了java定时任务框架elasticjob详解,Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.该项目基于成熟的开源产品Quartz和Zo ...

  3. Springboot2 Quartz实现JAVA定时任务的动态配置

    动态配置Quartz.没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式 文章目录 一.需求背景 1. 问题现象 2. 问题分析 3. 解决方案 二.需求背景 2.1. maven依 ...

  4. Java定时任务(一) Timer及TimerTask的案例解析及源码分析

    Java定时任务(一)  Timer及TimerTask的案例解析及源码分析 一.概述: 定时任务这个概念在Java的学习以及项目的开发中并不陌生,应用场景也是多种多样.比如我们会注意到12306网站 ...

  5. Java定时任务技术分析

    <从零打造项目>系列文章 工具 比MyBatis Generator更强大的代码生成器 ORM框架选型 SpringBoot项目基础设施搭建 SpringBoot集成Mybatis项目实操 ...

  6. Java 定时任务详解

    文章目录 单机定时任务技术选型 Timer ScheduledExecutorService Spring Task 时间轮 分布式定时任务技术选型 Quartz Elastic-Job XXL-JO ...

  7. JAVA定时任务怎么实现

    序章:定时任务实现方式 当下,java编码过程中,实现定时任务的方式主要以以下两种为主 spring框架的@Scheduled quzrtz框架 网络上关于这两种框架的实践和配置相关的教程很多,这里不 ...

  8. SpringBoot下使用定时任务的方式全揭秘

    本文旨在用通俗的语言讲述枯燥的知识 定时任务作为一种系统调度工具,在一些需要有定时作业的系统中应用广泛,如每逢某个时间点统计数据.在将来某个时刻执行某些动作-定时任务在主流开发语言均提供相应的API供 ...

  9. JAVA定时任务-发送邮箱提醒-王大师王文峰开发(已上线完成)】

    本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,<Java王大师王天师>作者 公众号:山峯草堂,非技术多篇文章,专注于天道酬勤的 Java 开发问题.中国国学.传统文化和代 ...

最新文章

  1. STM32-USART控制led和蜂鸣器
  2. 一个数里有那些约数用c++怎么做_嵌入式就业的那些事~
  3. 弯道极限超车、击败人类顶级玩家,索尼AI赛车手登上Nature封面
  4. python 的日志logging模块学习
  5. @ImportResource
  6. 互联网1分钟 | 1011
  7. C语言素数分解prime factoriziation算法(附完整源码)
  8. 构造、拷贝构造、赋值、析构
  9. IDEA clone项目
  10. idea license 20200104
  11. 从单张图重建三维人体模型综述(六)
  12. iOS5编程--官方例子代码的研究--2.UICatalog-6
  13. python-map()/reduce()/filter()/sorted()/排列组合
  14. wireshark分析PS流格式解析详解
  15. Java程序员“金三银四“就一定要出去面试吗?
  16. 天梯赛省赛选拔赛复盘
  17. 一键解锁,宿舍管理隐藏技能
  18. 计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序
  19. 【C语言算法】归并排序
  20. 开发简单Android聊天软件(7)

热门文章

  1. 2022CCPC网络预选赛c题Problem C. Guess
  2. 百度地图api周边搜索功能,用单选按钮切换搜索类型
  3. 谈一谈,自身对技术经理这个职位的理解吧
  4. 黑盒子法探索人脑逻辑模型备忘录
  5. 计算机网络 层次路由,计算机网络-网络层(5)层次路由
  6. java 通过 ip地址 找到 打印机_有没有办法使用java套接字程序找到打印机状态?...
  7. HDTV 之-HDMI HPD
  8. (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  9. Flex布局和gird布局
  10. C# 将dataTable中的数据导出到excel表中