这是我参与新手入门的第2篇文章。
一、前言
在之前的文章《Java定时任务调度(1)TimerTask原理与实战》中已经介绍了一种实现定时任务调度的方法——Java原生提供的 TimerTask
,这个工具适用于一些简单的业务需求。
回顾一下,TimerTask的原理总结起来就是下面这个图:
其实仔细想想,是不是可以抽象出来几个部分?
任务调度,首先要有任务,TimerTask就是 具体任务
。有了任务之后是不是要给这个任务设置一下啥时候调,多久调一次,啥时候终止啊?这一步可以叫做 条件设置
。那么剩下的就是具体执行,可以叫做 执行器
。
其实就具体代码上来说,后两个都是调Timer的方法
Timer timer = new Timer();
long delay = 0;
long period = 1000;
timer.schedule(timerTask, delay, period);
但是,Timer存在一个严重的问题,它是 单线程
的。
如果你有多个任务,且第一个任务执行时间超过了两个任务的间隔时间,那么第二个任务就不能按时执行,此时可以选择使用ScheduledExecutorService来解决,它的内部是个线程池,此外它也能解决上篇文章中提到的Timer异常退出问题。
二、Quartz的简单介绍
那么接下来,就按照这个思路来介绍一个更强大的Java任务调度框架——Quartz
Quartz有一个官方版的简单介绍:
Quartz 允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。
如果从来没有接触过任务调度的东西,光看这肯定也懵,不过相信你看完全篇再回过头来,就明白了。
说来也巧,Quartz的设计思路就是上面总结的三部分,只不过名字不同。
-
Job:具体要执行的任务逻辑
-
Trigger:触发器,设置Job的触发条件、间隔,终止时间
-
Scheduler:调度器,启动Trigger执行Job
这么看是不是和前言中对TimerTask的总结一致了?
Quartz Demo的创建
如果使用传统方式,就是去官方下载一个jar包,新建一个Java project,导包就可以了。 现在一般都是使用自动化构建工具了。
打开start.spring.io/ 填写相关配置,这里我使用Maven
当然此处也可以选择右侧的add dependencies,那我一般都是自己在pom文件中添加依赖。
导入依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
写Demo
public static void main(String[] args) {
try {
// 工厂方法获取默认的调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 启动
scheduler.start();
//关闭
scheduler.shutdown();
} catch (SchedulerException se) {
se.printStackTrace();
}
}
其实这个例子是官网提供的【www.quartz-scheduler.org/documentati… 很简单,一共就三行代码。
执行结果是什么那?
22:47:27.348 [main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
22:47:27.355 [main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
22:47:27.370 [main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
22:47:27.370 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.2 created.
22:47:27.371 [main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
22:47:27.372 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.2) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
22:47:27.372 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
22:47:27.372 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.2
22:47:27.372 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
22:47:27.372 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
22:47:27.372 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
22:47:27.372 [main] DEBUG org.quartz.simpl.SimpleThreadPool - Shutting down threadpool...
22:47:27.372 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 0 triggers
22:47:27.372 [main] DEBUG org.quartz.simpl.SimpleThreadPool - Shutdown of threadpool complete.
22:47:27.372 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
22:47:27.868 [DefaultQuartzScheduler_Worker-6] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-10] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-5] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-4] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-3] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.869 [DefaultQuartzScheduler_Worker-2] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.869 [DefaultQuartzScheduler_Worker-1] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-7] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-8] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
22:47:27.868 [DefaultQuartzScheduler_Worker-9] DEBUG org.quartz.simpl.SimpleThreadPool - WorkerThread is shut down.
输出的结果还是有很多看头的
Quartz Scheduler v.2.3.2 created 可以看到使用版本
RAMJobStore initialized 可以看到存储方式是RAMJobStore
最后面的SimpleThreadPool 就是线程池,一共有1-10 10个线程
看到线程池,你会想到什么?
可以参考我的上篇文章:《Java定时任务调度(1)TimerTask原理与实战》
假如我把第三行代码注释掉,会发生什么? 注意箭头的位置,这个程序并没有停止。
这里官网也有解释:
Once you obtain a scheduler using StdSchedulerFactory.getDefaultScheduler(), your application will not terminate until you call scheduler.shutdown(), because there will be active threads.
一旦使用StdSchedulerFactory.getDefaultScheduler()获得调度程序,在调用scheduler.shutdown()之前,应用程序不会终止,因为会有活动线程。
有了启动和停止,任务的具体执行自然就在这中间来完成。
把官网的例子复制过来,很明显,出现了错误。 具体原因就是一个是没有HelloJob这个类,另一个静态导入要补上
public class HelloJob implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("你好!当前时间是:"+simpleDateFormat.format(new Date()));
}
}
//注意,静态导入不在这个HelloJob类中
import static org.quartz.JobBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
当然在执行之前,一定要在停止的前面加上Thread.sleep(),要不然,直接就关闭了。
为了尽快的看到效果,我把间隔时间设置为5秒
效果:
好了,简单的Demo就写好了。
更详细深入的内容在后续文章中~