一、@Scheduled注解
這是基於注解可實現定時任務。
實現:
1、
@EnableScheduling注解到定時方法的類上,或者直接注解到啟動類。
2、
@Scheduled注解到定時方法上
@Scheduled有以下參數:
1 @Scheduled(fixedDelay = 3000) //方法執行完成后等待3秒再次執行 2 @Scheduled(fixedRate = 3000) //方法每隔3秒執行一次 3 @Scheduled(initialDelay = 2000,fixedRate = 4000) //延遲2秒執行第一次,之后每隔4秒執行一次 4 @Scheduled(fixedDelayString ="${time.demo}") //可以執行配置文件中的,方法執行完成后等待time.demo再次執行 5 @Scheduled(fixedRateString ="${time.demo}" ) //可以執行配置文件中的,法每隔time.demo執行一次 6 @Scheduled(cron = "0 0,30 0,8 ? * ? ") //cron表達式,方法在每天的8點30分0秒執行,參數為字符串類型
cron表達式,推薦看這篇文章:https://www.jianshu.com/p/1defb0f22ed1
示例:
每隔3秒執行一次。
1 @Component 2 @EnableScheduling 3 public class testScheduled { 4 5 @Scheduled(fixedRate = 3000) 6 public void call(){ 7 System.out.println("每隔3秒打印一次"); 8 } 9 }
優點:簡單,只需要兩個注解即可
缺點:參數和方法都必須寫到代碼里面
二、Timer().schedule創建任務
直接上示例,2秒后執行第一次,然后每隔4秒執行一次。
1 @Component 2 public class testTimer { 3 { 4 doTimer(); 5 } 6 public void doTimer(){ 7 //創建timer對象 8 Timer timer = new Timer(); 9 //創建TimerTask對象 10 TimerTask timerTask = new TimerTask() { 11 //重寫run方法,就是具體定時做什么事情 12 @Override 13 public void run() { 14 System.out.println(new Date().toString()); 15 } 16 }; 17 //timer來執行timerTask 18 timer.schedule(timerTask,2000,4000); 19 } 20 }
幾個概念:
Timer:即定時器,為java自帶的工具類,提供定時執行任務的相關功能
timer有3個核心方法:
1、添加任務(6種)
schedule(TimerTask task, long delay):指定任務task,在delay毫秒延遲后執行 schedule(TimerTask task, Date time):指定任務task,在time時間點執行一次 schedule(TimerTask task, long delay, long period):指定任務task,延遲delay毫秒后執行第一次,並在之后每隔period毫秒執行一次 schedule(TimerTask task, Date firstTime, long period):指定任務task,在firstTime的時候執行第一次,之后每隔period毫秒執行一次 scheduleAtFixedRate(TimerTask task, long delay, long period):作用與schedule一致 scheduleAtFixedRate(TimerTask task, Date firstTime, long period):作用與schedule一致 實際上最后都會使用sched(TimerTask task, long time, long period),即指定任務task,在time執行第一次,之后每隔period毫秒執行一次 schedule使用系統時間計算下一次,即System.currentTimeMillis()+period 而scheduleAtFixedRate使用本次預計時間計算下一次,即time + period 對於耗時任務,兩者區別較大,請按需求選擇,瞬時任務無區別。
2、取消任務方法:cancel(),會將任務隊列清空,並堵塞線程,且不再能夠接受任務(接受時報錯),並不會銷毀本身的實例和其內部的線程。
3、凈化方法:purge(),凈化會將隊列里所有被取消的任務移除,對剩余任務進行堆排序,並返回移除任務的數量。
TimerTask:實際上就是一個Runnable而已,繼承Runnable並添加了幾個自定義的參數和方法,說白了就是在這里面寫定時的具體方法。
TaskQueue:即任務隊列,Timer生產任務,然后推到TaskQueue里存放,等待處理,被處理掉的任務即被移除掉。
注:TaskQueue
實質上只有一個長度為128的數組用於存儲TimerTask
、一個int型變量size表示隊列長度、以及對這兩個數據的增刪改查。
TimerThread:即定時器線程,線程會共享TaskQueue里面的數據,TimerThread會對TaskQueue里的任務進行消耗。
注:TimerThread
實際上就是一個Thread
線程,會不停的監聽TaskQueue
,如果隊列里面有任務,那么就執行第一個,並將其刪除(先刪除再執行)。
三、線程
1、通過線程的sleep來造成延時的效果
示例1:thread + runnable
1 @Component 2 public class testThreadAndRunnable { 3 4 private Integer count = 0; 5 6 public testThreadAndRunnable() { 7 test1(); 8 } 9 public void test1() { 10 new Thread(() -> { 11 while (count < 10) { 12 System.out.println(new Date().toString() + ": " + count); 13 count++; 14 try { 15 Thread.sleep(3000); 16 } catch (InterruptedException e) { 17 e.printStackTrace(); 18 } 19 } 20 }).start(); 21 } 22 }
示例2:線程池 + runnable
1 @Component 2 public class testThreadPool { 3 private static final ExecutorService threadPool = Executors.newFixedThreadPool(5);// 線程池 4 private Integer count = 0; 5 public testThreadPool() { 6 test2(); 7 } 8 public void test2() { 9 threadPool.execute(() -> { 10 while (count < 10) { 11 System.out.println(new Date().toString() + ": " + count); 12 count++; 13 try { 14 Thread.sleep(3000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 } 19 }); 20 } 21 }
2、使用ScheduledTask + runnable
示例:
@Component public class testScheduledTask { private Integer count = 0; @Autowired private TaskScheduler taskScheduler; public testScheduledTask(TaskScheduler taskScheduler) { this.taskScheduler = taskScheduler; test4(); test5(); test6(); } //設置間隔時間,每2秒執行一次 public void test4() { taskScheduler.scheduleAtFixedRate(() -> { System.out.println(new Date().toString() + ": " + count+"設置間隔時間2秒"); count++; }, 2000); } //可以用Cron表達式,每天凌晨1點執行 public void test5() { taskScheduler.schedule(() -> { System.out.println(new Date().toString() + ": " + count+"凌晨1點執行"); count++; }, new CronTrigger("0 0 1 * * ?")); } //設置間隔時間,每5.5秒執行一次 public void test6() { taskScheduler.scheduleAtFixedRate(() -> { System.out.println(new Date().toString() + ": " + count+"設置間隔時間5.5秒"); count++; }, 5500); } }
四、Quartz
1、導入Quartz的jar包
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency>
2、實現的整體結構
2.1、創建定時任務對象的Job
//創建定時任務的對象 public class MyQuartz implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { Date date = new Date(); String format = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(date); System.out.println("======響應時間為:"+format); } }
2.2、創建執行類
@Component public class MySchedule { public MySchedule() throws SchedulerException { doQ(); } public void doQ() throws SchedulerException { //1、調度器Scheduler的創建 Scheduler scheduler = new StdSchedulerFactory().getScheduler(); //2、創建JobDetail實例,並綁定執行類 JobDetail job = JobBuilder.newJob(MyQuartz.class).withIdentity("Quartz1", "QuartzGroup1").build(); //3、構建Trigger實例 CronTrigger build = TriggerBuilder.newTrigger().withIdentity("Trigger1", "QuartzTrigger1") .startNow() .withSchedule(CronScheduleBuilder.cronSchedule("2/3 * * * * ? *")) .build(); //4、執行Quartz scheduler.scheduleJob(job,build); scheduler.start(); }
corn表達式生成地址:https://cron.qqe2.com/
上述corn表達式指,2秒后開始執行,每3秒執行一次。
2.3、可以通過一些延時操作來控制任務停止時間
//5.利用TimeUnit實現延時操作 TimeUnit.SECONDS.sleep(30); //6.關閉定時任務 scheduler.shutdown(); System.out.println("定時任務結束!");
Quartz參考博客:https://blog.csdn.net/qq_41011626/article/details/113740186
其他參考博客:(118條消息) 【JAVA定時器】四種常見定時器的原理和簡單實現_Echo-YeZi的博客-CSDN博客_java 定時器