定时任务的实现方法主要有 Timer、Quartz 以及 @Scheduled,实现SchedulingConfigurer 接口。

实际使用中我们往往想从数据库中读取指定时间来动态执行定时任务,这时候基于接口的定时任务就派上用场了。

 

Timer 实现定时任务

只执行一次的定时任务



Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("2000毫米后执行一次。");
}
}, 2000);

timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("5000毫米后执行一次。");
}
}, new Date(System.currentTimeMillis() + 5000));


循环执行任务



Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(111);
}
}, 1000, 2000); // 1000毫米后执行第一次,之后每2000毫米执行一次


终止任务



timer.concel();


Timer 是 JDK 实现的定时任务,用起来简单、方便,对一些简单的定时任务可以使用它。由于它不支持 cron 表达式,现在已经很少用了。

Quartz 实现定时任务

Quartz 是一个完全由 Java 编写的开源作业调度框架,可以用它来实现定时任务。

在 pom.xml 文件添加 Quartz 依赖



<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.6</version>
</dependency>


编写 Job



public class QuartzJob implements Job{

public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String hello = (String) jobDataMap.get("hello");
System.err.println(hello);
}

}


编写 Task



public void task() {
// 该 map 可在 job 中获取
JobDataMap map = new JobDataMap();
map.put("hello", "world");

JobDetail jobDetail = newJob(QuartzJob.class).
withIdentity("myJob", "myGroup").
setJobData(map).build();
/*
* 简单定时器
*
* 执行时间间隔
* withIntervalInMilliSeconds 毫秒
* withIntervalInSeconds 秒
* withIntervalInMinutes 分钟
* withIntervalInHours 小时
*
* 执行次数
* repeatForever 重复执行
* withRepeatCount 次数
*/
SimpleScheduleBuilder scheduleBuilder = simpleSchedule().withIntervalInSeconds(3).withRepeatCount(10);

/*
* corn定时器
*
* corn表达式,使用更灵活
* corn表达式在线生成 http://cron.qqe2.com/
*/
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0 0 1 * ?");

Trigger trigger = newTrigger().startAt(new Date()).//startNow() 默认现在开始
withIdentity("myTrigger", "myGroup").
//withSchedule(scheduleBuilder).build();
withSchedule(cronScheduleBuilder).build();

try {
//1.创建Scheduler工厂
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
//2.获取实例
Scheduler scheduler = schedulerFactory.getScheduler();
//3.设置jobDetail详情和trigger触发器
scheduler.scheduleJob(jobDetail, trigger);
//4.定时任务开始
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}

}


在项目启动的时候调用 task 方法即可启动定时任务。

Spring Boot 创建定时任务

Spring Boot 默认已经实现了定时任务,只需要添加相应的注解即可完成

pom.xml 文件配置

pom.xml 不需要添加其他依赖,只需要加入 Spring Boot 依赖即可,这里我们添加一个 ​​web​​ 和 ​​test​​ 的依赖



<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


在启动类上面加上 @EnableScheduling 注解

在启动类上面加上 ​​@EnableScheduling​​ 注解即可开启定时任务



@EnableScheduling
@SpringBootApplication
public class SchedulingApplication {

public static void main(String[] args) {
SpringApplication.run(SchedulingApplication.class, args);
}
}


编写定时任务、注意这个方法的返回值需要为void。



@Scheduled(cron = "*/2 * * * * ?")
public void task3() {
System.out.println("每2秒执行一次!");
}


 

多线程定时任务

1、启动类加这个注解@EnableAsync // 2.开启多线程/2、

2、定时任务方法上加这个注解@Async

3、查看结果。可以看到定时任务是多线程实现的。

 

动态定时任务:基于接口、可以读数据库拿到定时任务执行时间



@Component
@Configuration //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling // 2.开启定时任务
public class DynamicScheduleTask implements SchedulingConfigurer {

@Mapper
public interface CronMapper {
@Select("select cron from cron limit 1")
public String getCron();
}

@Autowired //注入mapper
@SuppressWarnings("all")
CronMapper cronMapper;

/**
* 执行定时任务.
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

taskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
() -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库获取执行周期
String cron = cronMapper.getCron();
//2.2 合法性校验.
if (StringUtils.isEmpty(cron)) {
// Omitted Code ..
}
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}

}


启动 Spring Boot 项目在控制台就会看到任务定时执行。


莫听穿林打叶声,何妨吟啸且徐行!!!