常见定时任务:
1、常见定时任务 Java自带的java.util.Timer类
timer:配置比较麻烦,时间延后问题
timertask:不推荐
2、Quartz框架
配置更简单
xml或者注解
3、SpringBoot使用注解方式开启定时任务
1)启动类里面 @EnableScheduling开启定时任务,自动扫描
2)定时任务业务类 加注解 @Component被容器扫描
3)定时执行的方法加上注解 @Scheduled(fixedRate=2000) 定期执行一次
定时任务配置:
1、cron 定时任务表达式 @Scheduled(cron="*/1 * * * * *") 表示每秒
1)crontab 工具 https://tool.lu/crontab/
2、fixedRate: 定时多久执行一次(上一次开始执行时间点后xx秒再次执行;)
3、fixedDelay: 上一次执行结束时间点后xx秒再次执行
4、fixedDelayString: 字符串形式,可以通过配置文件指定
Cron表达式参数分别表示:
- 秒(0~59) 例如0/5表示每5秒
- 分(0~59)
- 时(0~23)
- 日(0~31)的某天,需计算
- 月(0~11)
- 周几( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)
@Scheduled:除了支持灵活的参数表达式cron之外,还支持简单的延时操作,例如 fixedDelay ,fixedRate 填写相应的毫秒数即可。
例子:
package com.sw.cooke.task; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; @Component @EnableScheduling //标记定时任务 public class testTask { //@Scheduled(fixedRate = 2000l) @Scheduled(cron = "0/5 * * * * ?")//5秒 public void test(){ System.out.println("定时任务开始时间"+new Date()); } }
多线程异步定时任务:
package com.sw.cooke.task; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.util.concurrent.Future; /** * @Description: 自定义异步任务 * @author: panboyang * @date :2019-07-03 11:23:31 * @params: No such property: code for class: Script1 */ @Component @EnableAsync//开启线程 public class AsyncTask { @Async//开启异步 @Scheduled(fixedDelay = 1000) //间隔1秒 public void task1() throws InterruptedException { long begin = System.currentTimeMillis(); Thread.sleep(1000L); long end = System.currentTimeMillis(); System.out.println("任务1耗时=" + (end - begin)+"任务1开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName()); } @Async @Scheduled(fixedDelay = 1000) //间隔1秒 public void task2() throws InterruptedException { long begin = System.currentTimeMillis(); Thread.sleep(2000L); long end = System.currentTimeMillis(); System.out.println("任务2耗时=" + (end - begin)+"任务2任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName()); } @Async @Scheduled(fixedDelay = 1000) //间隔1秒 public Future<String> task4() throws InterruptedException { long begin = System.currentTimeMillis(); Thread.sleep(2000L); long end = System.currentTimeMillis(); System.out.println("任务4耗时=" + (end - begin)+"任务4开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName()); return new AsyncResult<String>("任务4"); } @Async @Scheduled(fixedDelay = 1000) //间隔1秒 public Future<String> task5() throws InterruptedException { long begin = System.currentTimeMillis(); Thread.sleep(3000L); long end = System.currentTimeMillis(); System.out.println("任务5耗时=" + (end - begin)+"任务5开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName()); return new AsyncResult<String>("任务5"); } }
从控制台可以看出,任务1和任务4互不影响;
并且,由于开启了多线程,任务1的执行时间也不受其本身执行时间的限制,所以需要注意可能会出现重复操作导致数据异常