一、定時
1、定時任務的適用場景
定時任務的場景可以說非常廣泛,比如某些視頻網站,購買會員後,每天會給會員送成長值,每月會給會員送一些電影券;比如在保證最終一致性的場景中,往往利用定時任務調度進行一些比對工作;比如一些定時需要生成的報表、郵件;比如一些需要定時清理數據的任務等。
2、定時任務實現的四種方式
JDK定時類、Quartz 框架、Spring註解定時和xml配置、SpringBoot定時任務。
二、JDK定時
Timer是一種定時器工具,用來在一個後臺線程計劃執行指定任務。它可以計劃執行一個任務一次或反覆多次。
TimerTask一個抽象類,它的子類代表一個可以被Timer計劃的任務。具體的任務在TimerTask中run接口中實現。
通過Timer中的schedule方法啓動定時任務。
1、在指定日期運行定時器任務,只運行一次
public static void main(String[] args) throws ParseException {
String sdate = "2018-02-14";
SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
Date date = sf.parse(sdate);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("系統正在運行……");
}
}, date); //在指定的日期運行一次定時任務
/*如果date日期在今天之前,則啓動定時器後,立即運行一次定時任務run方法*/
/*如果date日期在今天之後,則啓動定時器後,會在指定的將來日期運行一次任務run方法*/
}
2、在距當前時刻的一段時間後運行定時器任務,只運行一次
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("系統正在運行……");
}
}, 5000); //指定啓動定時器5s之後運行定時器任務run方法,並且只運行一次
}
3、在指定的時間後,每隔指定的時間,重複運行定時器任務
public static void main(String[] args) throws ParseException {
String sdate = "2018-02-10";
SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
Date date = sf.parse(sdate);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("系統正在運行……");
}
}, date, 2000);
/*如果指定的date時間是當天或者今天之前,啓動定時器後會立即每隔2s運行一次定時器任務*/
/*如果指定的date時間是未來的某天,啓動定時器後會在未來的那天開始,每隔2s執行一次定時器任務*/
}
4、在距當前時刻的一段指定距離後,每隔指定時間運行一次定時器任務
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("系統正在運行……");
}
}, 5000, 2000);
/*當啓動定時器後,5s之後開始每隔2s執行一次定時器任務*/
}
停止定時器的四種方式
1、調用Timer的cancel方法;
2、把Timer線程設置成Daemon守護線程,當所有的用戶線程結束後,那麼守護線程也會被終止;
3、當所有的任務執行結束後,刪除對應Timer對象的引用,線程也會被終止;
4、調用System.exit方法終止程序
三、Quartz
Quartz是一個完全由Java編寫的開源作業調度框架,爲在Java應用程序中進行作業調度提供了簡單卻強大的機制。
1、pom文件
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
2、實現job接口在execute方法寫相關業務
public class TestJob implements Job {
private Logger logger = LoggerFactory.getLogger(TestJob.class);
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("業務寫在這裏");
logger.info(Thread.currentThread().getName() + " test job begin " + new Date());
}
}
3、測試類
public static void main(String[] args) throws InterruptedException, SchedulerException {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
// 開始
scheduler.start();
// job 唯一標識 test.test-1
JobKey jobKey = new JobKey("test" , "test-1");
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("test" , "test")
// 延遲一秒執行
.startAt(new Date(System.currentTimeMillis() + 1000))
// 每隔一秒執行 並一直重複
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
.build();
scheduler.scheduleJob(jobDetail , trigger);
Thread.sleep(5000);
// 刪除job
scheduler.deleteJob(jobKey);
}
public static void main(String[] args) throws InterruptedException, SchedulerException {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
// 開始
scheduler.start();
// job 唯一標識 test.test-1
JobKey jobKey = new JobKey("test" , "test-1");
JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
// 可以設置定時任務具體時間
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("test", "test-1").withSchedule(
CronScheduleBuilder.cronSchedule("/2 * * * * ?")
).build();
scheduler.scheduleJob(jobDetail , trigger);
Thread.sleep(5000);
// 刪除job
scheduler.deleteJob(jobKey);
}
四、Spring定時
1、註解版本
<task:annotation-driven />
配置掃描任務位置
<!-- 掃描任務 -->
<context:component-scan base-package="com.vrveis.roundTrip.task" />
package com.vrveis.roundTrip.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class FlightTrainTask {
@Scheduled(cron = "0/5 * * * * ? ") // 間隔5秒執行
public void taskCycle() {
System.out.println("使用Spring框架配置定時任務");
}
}
2、Xml版本
<context:component-scan base-package="com" />
<!-- spring框架的Scheduled定時器 -->
<task:scheduled-tasks>
<task:scheduled ref="springTiming" method="test" cron="0 0 12 * * ?"/>
</task:scheduled-tasks>
public class SpringTiming {
public void test(){
System.out.println("使用Spring定時任務");
}
}
五、SpringBoot實現定時
1、pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
2、啓動類添加@EnableScheduling 註解
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3、創建定時任務類
@Component
public class SchedulerTask {
private Logger logger = LoggerFactory.getLogger(SchedulerTask.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
private int count = 0;
@Scheduled(cron="*/6 * * * * ?")
private void process(){
logger.info("this is scheduler task runing "+(count++));
}
@Scheduled(fixedRate = 6000)
public void reportCurrentTime() {
logger.info("現在時間:" + dateFormat.format(new Date()));
}
}
4、運行結果
2019-01-19 14:49:12.025 INFO 17024 --- [pool-1-thread-1]
c.example.springbootdemo.SchedulerTask : this is scheduler task runing 0
2019-01-19 14:49:13.109 INFO 17024 --- [pool-1-thread-1]
c.example.springbootdemo.SchedulerTask : 現在時間:14:49:13
通過運行結果看到是一個線程執行定時任務,如果在同一時間啓動多個定時器怎麼辦?
增加一個配置類
@Configuration
//所有的定時任務都放在一個線程池中,定時任務啓動時使用不同都線程。
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//設定一個長度10的定時任務線程池
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
測試結果可以看出現在是多個線程運行定時器。
2019-01-19 14:51:30.025 INFO 18392 --- [pool-1-thread-2]
c.example.springbootdemo.SchedulerTask : this is scheduler task runing 0
2019-01-19 14:51:32.214 INFO 18392 --- [pool-1-thread-1]
c.example.springbootdemo.SchedulerTask : 現在時間:14:51:32
Cron表達式
corn從左到右(用空格隔開):秒 分 小時 月份中的日期 月份 星期中的日期 年份
Cron表達式生成器
http://cron.qqe2.com/