在线corn表达式

1. 总结常见的实现定时任务的几种方法

  • thread实现 【原理:通过创建一个线程,让他在while循环里面一直运行,用sleep() 方法让其休眠从而达到定时任务的效果。】
  • Timer类
  • ScheduledExcecutorService类
  • 使用spring的 spring-task 实现
  • Quartz

以下演示几种实现方式:每隔一秒打印一次hello world

1.1 thread实现

public static void main(String[] args) {
final long timeInterval = 1000; Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("hello world");
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}; Thread thread = new Thread(runnable);
thread.start();
}

1.2 Timer类实现

Timer是jdk中自带的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。但封装任务的类是TimerTask类(实际该类是一个抽象类,执行任务的代码要放在该类的子类中)。

TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。

构造方法:



成员方法:

public static void main(String[] args) {
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("Hello!Word!");
}
}; Timer timer = new Timer();
long delay = 0;
long intevalPeriod = 1 * 1000;
timer.scheduleAtFixedRate(task, delay, intevalPeriod);
}

schedule 与 scheduleAtFixedRate区别:

schedule会保证任务的间隔是按照定义的period参数严格执行的,如果某一次调度时间比较长,那么后面的时间会顺延,保证调度间隔都是period。
scheduleAtFixedRate是严格按照调度时间来的,如果某次调度时间太长了,那么会通过缩短间隔的方式保证下一次调度在预定时间执行。

线程安全, 但只会单线程执行, 如果执行时间过长, 就错过下次任务了, 抛出异常时, timerWork会终止

启动和取消任务是可以控制的

1.3 ScheduledExcecutorService类实现

ScheduledExecutorService是JDK1.5以后java.util.concurrent中的一个接口, 用于实现定时任务。

public static void main(String[] args) {
Runnable r1 = new Runnable() {
public void run() {
System.out.println("Hello Word");
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(r1, 3, 1, TimeUnit.SECONDS);// 3秒后开始执行
}

他是通过线程池的方式执行任务,可以多线程执行。

启动和取消任务是可以控制的

可以设定第一次的延迟时间

1.4 使用spring提供的 spring-task 实现

a) 只需要导入web的starter依赖

b) 在启动类上添加 @EnableScheduling 注解

c) 用 @Scheduled 注解开启一个定时任务。

@Component
public class SchedulerTask {
private int count = 0; /**
* @Author Smith
* @Description 设置每1秒执行一次
* @Date 14:23 2019/1/24
* @Param
* @return void
**/
@Scheduled(cron = "*/1 * * * * ?") // 基于cron表达式实现
private void process(){
System.out.println("hello world " + (count++));
}
}

@Scheduled 该注解的常用参数说明【不基于cron表达式实现的时候】:

fixedRate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。

fixedDelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。

initialDelay 表示首次任务启动的延迟时间。

所有时间的单位都是毫秒。

1.5 Quartz

参考

源码

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。

Quartz默认是多线程异步执行,单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。

Quartz支持集群定时任务

Quartz与Spring Task区别

  • Quartz默认多线程异步执行,Task默认单线程同步执行。
  • Quartz单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。Task单个任务时,当前次的调度完成后,再执行下一次任务调度。
  • Quartz多个任务时,任务之间没有直接影响,多任务执行的快慢取决于CPU的性能。Task多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池
  • Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务

两者对比总结:

1、实现,Task注解实现方式,比较简单。Quartz需要手动配置Jobs。

2、任务执行,Task默认单线程串行执行任务,多任务时若某个任务执行时间过长,后续任务会无法及时执行。Quartz采用多线程,无这个问题。

3、调度,Task采用顺序执行,若当前调度占用时间过长,下一个调度无法及时执行;

4、Quartz采用异步,下一个调度时间到达时,会另一个线程执行调度,不会发生阻塞问题,但调度过多时可能导致数据处理异常

5、部署,Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务

Quartz 核心概念:

a) Job 表示一个工作,要执行的具体内容。此接口中只有一个方法。Task多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池。

void execute(JobExecutionContext context)

b) JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。

c) Trigger 代表一个调度参数的配置,什么时候去调。

d) Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

Spring Boot整合Quartz:

  1. 导入Quartz依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 编写任务类
public class Task implements Job {

        // 任务类不能直接注入Bean,若想注入Bean需要配置第4步
@Autowired
private TestService service; private void before(){
System.out.println("定时任务开始");
} @Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
service.testDemo();
System.out.println("hello quartz");
} private void afer(){
System.out.println("定时任务结束");
}
}
★ 任务类不能直接注入Bean,若想注入Bean需要配置第4步 ★
  1. 编写Quartz配置
@Configuration
public class QuartzConfig { @Bean
public JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
//关联我们自己的Job类
factory.setJobClass(Task.class);
return factory;
} @Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean) {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetailFactoryBean.getObject());
//设置触发时间
factory.setCronExpression("0/2 * * * * ?");
return factory;
} @Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyAdaptableJobFactory jobFactory) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//关联trigger
factory.setTriggers(cronTriggerFactoryBean.getObject());
factory.setJobFactory(jobFactory);
return factory;
}
}
  1. 编写配置【用于任务类能注入我们的bean】
@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory { // 可以将一个对象添加到SpringIOC 容器中,并且完成该对象注入
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory; /**
* 该方法需要将实例化的任务对象手动的添加到springIOC 容器中并且完成对象的注入
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object obj = super.createJobInstance(bundle);
//将obj 对象添加Spring IOC 容器中,并完成注入
this.autowireCapableBeanFactory.autowireBean(obj);
return obj;
}
}

2 Quartz[群集环境]

使用quartz实现定时任务[单机版],若是部署多台机器,那么到了时间点,多台服务器便会同时均开始执行定时任务。

Quartz是能适用于分布式集群环境的,在同一时间只会有一台机器执行定时任务。

Quartz 中集群如何工作:

一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。离开了db将无法感知

2.1 导入依赖

<!-- spring boot2.x + quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2.2 数据库建表

到官网下载

下载之后解压,进入如下目录,创建数据库表:









11张表功能说明:

最新文章

  1. .NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式
  2. thinkphp 3.2视图里添加URL参数 实例
  3. 包含min函数的栈
  4. 【实习记】2014-09-01从复杂到简单:一行命令区间查重+长整型在awk中的bug
  5. 复杂对象创建终结者(Builder Pattern)
  6. Java8 HashMap之tableSizeFor
  7. 调用CImg库显示WAV格式音频波形
  8. python web -- django
  9. 数据结构 Python实现
  10. vue 父子组件的方法调用
  11. UVA506-System Dependencies(拓扑序)
  12. document.forms用法示例介绍
  13. .NET拾忆:FileSystemWatcher 文件监控
  14. linux安装python3 ,安装IPython ,安装jupyter notebook
  15. Spring Cloud搭建手册(2)——Spring Cloud Config
  16. ScoketTimeout Exception浅析
  17. REPEAT_BYTE(x)宏
  18. springboot 整合dubbo 消费模块引入springboot 之后自动注入jdbc 模块导致启动报错问题
  19. EditText中输入信息的限制的方法
  20. Python基础——类

热门文章

  1. 【Linux】1、命令行及命令参数
  2. Netty的简单Demo
  3. [APUE] 进程环境
  4. Seata RPC 模块的重构之路
  5. 电脑微信电脑PC 多开/防撤回 补丁
  6. 如何使用 Vuepress
  7. __del__ PyPy和CPython的不同点 动态编译(注意不是解释) 析构函数被调用的次数
  8. http发送
  9. TCMalloc源码学习(四)(小内存块释放)
  10. LOJ10082