程序員可以讓步,卻不可以退縮,可以羞澀,卻不可以軟弱,總之,程序員必須是勇敢的。
一:序言
公司近期有一個項目需要用到定時功能,於是安排我調研一下java能用的定時器,要求如下:
- 配置簡單
- 方便啓停
- 運行準確可靠
二:調研過程
第一步—尋找定時器
這個過程大約花了我10分鐘這麼多,各大網站,關鍵詞一搜,出來一大堆,簡單一比較,目前市面上用的比較多的定時器主要有下面幾類:
序號 | 定時器 | 集成方式 |
1 | Timer | jdk自帶 |
2 | Thread | jdk自帶 |
3 | Spring(@Scheduled) | 需集成Spring/Spring Boot |
4 | quartz | 需依賴quartz jar包 |
第二步—分析定時器
看代碼:
1.Timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
//do something
}
//delay爲首次執行run需等待的時間(ms)
//period爲執行的週期(ms)
}, delay, period);
timer.cancel();//關閉定時器
2.Thread
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
// do something
try {
Thread.sleep(timeInterval);//每隔**ms run一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
3.@Scheduled
(1)添加類的註解
@Component//把類注入Spring的上下文
@EnableScheduling//開啓定時任務
(2)定時器
關於cron的定義 百度一下就有很多
@Scheduled(cron = "0/1 * * * * * ?")
private void task(){
//do something
}
4.quartz
(1)添加依賴 pom/jar/gradle
//pom
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.4.0</version>
</dependency>
//gradle
implementation 'org.quartz-scheduler:quartz:2.4.0'
(2)添加配置
org.quartz.scheduler.instanceName = MyScheduler//調度名稱
org.quartz.threadPool.threadCount = 3 //線程數量
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore//RAM
(3)定時器
public class QuartzTest {
public static void main(String[] args) {
try {
// Grab the Scheduler instance from the Factory
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// and start it off
scheduler.start();
scheduler.shutdown();
} catch (SchedulerException se) {
se.printStackTrace();
}
}
}
爲了方便大家更好的進行選擇,在簡單的執行後,得出結論:
序號 | 定時器 | 集成難度 | 多線程難度 | 啓停難度 | 數據偏差 | 結論 |
1 | Timer |
無需集成 |
中 | 易 | 大 | 別用了,誤差大 |
2 | Thread | 無需集成 | 中 | 中 | 中 | 別用了,太麻煩 |
3 | Spring(@Scheduled) | 易 | 易 | 易 | 小(0-3ms) | 輕量級Quartz |
4 | quartz | 中 | 易 | 易 | 小(0-3ms) | 框架重,配置複雜 |
第三步—選擇定時器
timer跟thread已經屬於比較落後的方法了,spring3.0以後自帶的scheduletask任務調度,不用配置就可以實現quartz的大部分功能,需要在定時器上有更深拓展的同學可以選擇Quartz,否則,選擇scheduletask吧!!!!
關於Quartz的使用詳解 大家可以看一下
"打入冷宮"的方法我們就不浪費時間進行贅述了,下面我將詳細描述單線程模式的ScheduleTask如何配置線程池進行有序的多調度,直接貼代碼
第四步—拓展定時器
1.目錄結構
2.yml文件
timer:
# 每一秒執行一次
corn1: 0/1 * * * * ?
corn2: 0/1 * * * * ?
3.Controller文件
@RestController
public class TestController {
@Autowired
private TestConfig testConfig;
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
private ScheduledFuture<?> future1;
private ScheduledFuture<?> future2;
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
@RequestMapping("/startCorn1")
public String startCorn1() {
future1 = threadPoolTaskScheduler.schedule(new MyRunnable(), new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
return new CronTrigger(testConfig.getCorn1()).nextExecutionTime(triggerContext);
}
});
System.out.println("startCron1()");
return "Start Corn1 Success";
}
@RequestMapping("/stopCron1")
public String stopCron1() {
if (future1 != null) {
future1.cancel(true);
}
System.out.println("stopCron1()");
return "Stop Corn1 Success";
}
@RequestMapping("/startCorn2")
public String startCorn2() {
future2 = threadPoolTaskScheduler.schedule(new MyRunnable2(), new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
return new CronTrigger(testConfig.getCorn2()).nextExecutionTime(triggerContext);
}
});
System.out.println("startCron2");
return "Start Cron2 Success";
}
@RequestMapping("/stopCron2")
public String stopCron2() {
if (future2 != null) {
future2.cancel(true);
}
System.out.println("stopCron2()");
return "Stop Corn2 Success";
}
}
4.Runnable文件
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable1---->");
}
}
5.config文件
@Component
@ConfigurationProperties(prefix = "timer")
public class TestConfig {
private String corn1;
private String corn2;
public String getCorn1() {
return corn1;
}
public void setCorn1(String corn1) {
this.corn1 = corn1;
}
public String getCorn2() {
return corn2;
}
public void setCorn2(String corn2) {
this.corn2 = corn2;
}
}
6.運行結果
(1)網頁運行結果
(2)打印臺顯示
三:結論