传统定时任务实现的几种方式:java
Timer:这是java自带的java.util.Timer类,这个类容许你调度一个java.util.TimerTask任务。使用这种方式可让你的程序按照某一个频度执行,但不能在指定时间运行。通常用的较少。
ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每一个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
Spring Task:Spring3.0之后自带的task,能够将它当作一个轻量级的Quartz,并且使用起来比Quartz简单许多。
Quartz:这是一个功能比较强大的的调度器,可让你的程序在指定时间执行,也能够按照某一个频度执行,配置起来稍显复杂。
复制代码
在SpringBoot项目中,咱们能够很简单的使用注解(@Scheduled)来实现定时任务express
首先了解一下@Scheduled这个注解bash
@Scheduled接受两种定时的设置:
一种是cornexpression。
一种是Rate/Delay表达式(毫秒值):
@Scheduled(fixedRate = 6000):上一次开始执行时间点后每隔6秒执行一次。
@Scheduled(fixedDelay = 6000):上一次执行完毕时间点以后6秒再执行。
@Scheduled(initialDelay=1000, fixedRate=6000):第一次延迟1秒后执行,以后按fixedRate的规则每6秒执行一次。
注:
*表示全部值,在分钟里表示每一分钟触发。在小时,日期,月份等里面表示每一小时,每一日,每一月。
?表示不指定值。表示不关心当前位置设置的值。 好比不关心是周几,则周的位置填写?。  主要是因为日期跟周是有重复的因此二者必须有一者设置为?
- 表示区间。小时设置为10-12表示10,11,12点均会触发。
,表示多个值。 小时设置成10,12表示10点和12点会触发。
/ 表示递增触发。 5/15表示从第5秒开始,每隔15秒触发。
L 表示最后的意思。 日上表示最后一天。星期上表示星期六或7。 L前加数据,表示该数据的最后一个。
星期上设置6L表示最后一个星期五。 6表示星期五
W表示离指定日期最近的工做日触发。15W离该月15号最近的工做日触发。
#表示每个月的第几个周几。 6#3表示该月的第三个周五。
示例:
"0 0 12 * * ?" 天天中午12点触发
"0 15 10 ? * *" 天天上午10:15触发
"0 15 10 * * ?" 天天上午10:15触发
"0 15 10 * * ? *" 天天上午10:15触发
"0 15 10 * * ? 2005" 2005年的天天上午10:15触发
"0 * 14 * * ?" 在天天下午2点到下午2:59期间的每1分钟触发
"0 0/5 14 * * ?" 在天天下午2点到下午2:55期间的每5分钟触发
"0 0/5 14,18 * * ?" 在天天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 14 * * ?" 在天天下午2点到下午2:05期间的每1分钟触发
"0 10,44 14 ? 3 WED" 每一年三月的星期三的下午2:10和2:44触发
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
"0 15 10 15 * ?" 每个月15日上午10:15触发
"0 15 10 L * ?" 每个月最后一日的上午10:15触发
"0 15 10 ? * 6L" 每个月的最后一个星期五上午10:15触发
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每个月的最后一个星期五上午10:15触发
"0 15 10 ? * 6#3" 每个月的第三个星期五上午10:15触发
天天早上6点 0 6 * * * 每两个小时 0 */2 * * *
晚上11点到早上8点之间每两个小时,早上八点 0 23-7/2,8 * * *
每月的4号和每一个礼拜的礼拜一到礼拜三的早上11点 0 11 4 * 1-3
1月1日早上4点 0 4 1 1 *
复制代码
在线Cron表达式生成器: cron.qqe2.com/多线程
在主类上使用@EnableScheduling注解开启对定时任务的支持并发
@Component
public class ScheduledTest {
private static Logger logger = LoggerFactory.getLogger(ScheduledTest.class);
@Scheduled(cron = "0/5 * * * * *")
public void scheduled(){
logger.info("=====>>>>>cron执行-{}",DateUtils.getCurrentDateMillTime());
}
@Scheduled(fixedRate = 5000)
public void scheduled1() {
logger.info("=====>>>>>fixedRate执行-{}", DateUtils.getCurrentDateMillTime());
}
@Scheduled(fixedDelay = 5000)
public void scheduled2() {
logger.info("=====>>>>>fixedDelay执行-{}",DateUtils.getCurrentDateMillTime());
}
}
复制代码
重启项目发现后台已经有任务在定时执行,时间间隔5秒异步
三个定时任务都已经执行,而且使同一个线程中串行执行,若是只有一个定时任务,这样作确定没问题,当定时任务增多,若是一个任务卡死,会致使其余任务也没法执行,这时候就要使用多线程执行ui
建立AsyncConfig类:spa
@Configuration
@EnableAsync //开启异步事件的支持
public class AsyncConfig {
@Value("${corePoolSize}")
private int corePoolSize;
@Value("${maxPoolSize}")
private int maxPoolSize;
@Value("${queueCapacity}")
private int queueCapacity;
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.initialize();
return executor;
}
}
复制代码
相应配置文件:线程
#定时任务配置
corePoolSize: 10
maxPoolSize: 200
queueCapacity: 10
复制代码
最后,在定时任务的类或者方法上添加@Async 。最后重启项目,每个任务都是在不一样的线程中,相互之间不影响设计