好久没写了。今天搞一下spring boot 的定时任务。
定时任务顾名思义,就是定时执行。
如何使用定时任务?
使用spring boot 定时任务需要:
1、开启定时任务:在启动类添加@EnableScheduling注解。
2、创建一个被spring 管理的bean组件。在定时任务的方法上添加注解@Scheduled。
例如:
@Component
public class MailTask {
@Scheduled(fixedRate=5000)
public void sendMail() {
log.info("第{}次定时发送邮件,现在时间:{}",sendMailCount++,JSONObject.toJSONStringWithDateFormat(new Date(),"yyyy-MM-dd HH:mm:ss,sss"));
}
如何设置定时任务的定时?
定时任务的时间设置使用@Scheduled注解的几个属性来实现。
举栗:
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.wm.springboot.sc.service.EmailService;
import lombok.extern.slf4j.Slf4j;
/**
* 定时任务
* @author maybe
*/
@Slf4j
@Component
public class MailTask {
@Autowired
private EmailService emailService;
private int sendMailCount = 1;
private int testCronCount = 1;
private int testFixedRate = 1;
private int testFixedDelay = 1;
/**
* initialDelay第一次延迟10秒执行,后续以重星开始为时间点,延迟5秒执行。
* 所有时间以毫秒为单位
*/
@Scheduled(fixedRate=5000,initialDelay = 10000)
public void sendMail() {
log.info("第{}次定时发送邮件,现在时间:{}",sendMailCount++,JSONObject.toJSONStringWithDateFormat(new Date(),"yyyy-MM-dd HH:mm:ss,sss"));
// emailService.sendMail(new Emails("240918567@qq.com", "83321164@qq.com", "测试定时任务", msgText, isEnclosure))
}
/**
* cron:时间表达式
*/
@Scheduled(cron="0/3 15-20 11,12 * * *")
public void testCron() {
log.info("第{}次测试cron定时任务-----",testCronCount++);
}
/**
* fixedRate 上一次开始执行时间点之后延迟多少秒执行
*/
@Scheduled(fixedRate=5000)
public void testFixedRate(){
try {
log.info("测试fixedRate,1111111111-----{}",testFixedRate++);
Thread.sleep(3000);
log.info("测试fixedRate,2222222222");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* fixedDelay 上一次执行完毕时间点后延迟执行
*/
@Scheduled(fixedDelay=5000)
public void testFixedDelay() {
try {
log.info("测试fixedDelay定时任务333333333-----{}",testFixedDelay++);
Thread.sleep(3000);
log.info("测试fixedDelay定时任务444444444");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这时候发现一个问题,就是我们执行定时任务都是一个线程执行的。
所以,如果需要多线程执行,需要配定时任务配置类,设置线程数。
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
/**
* 定时任务配置类
* 配置定时任务的并发数
* @author maybe
*/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer{
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
这时候再次执行:
这里多线程执行如果自己写一个线程来执行可不可以呢?
我试了一下,写一个线程是可以的。但是对于fixedDelay会有一个问题就是,他会和fixedRate一样,使用开始时间的后几秒,作为执行时间点。我觉得这可能和每次执行都是一个独立线程有关。具体还需要去学习研究一下。
cron时间表达式
这段是网上找的:
Seconds : 可出现", - * /"四个字符,有效范围为0-59的整数Minutes : 可出现", - * /"四个字符,有效范围为0-59的整数
Hours : 可出现", - * /"四个字符,有效范围为0-23的整数
DayofMonth : 可出现", - * / ? L W C"八个字符,有效范围为0-31的整数
Month : 可出现", - * /"四个字符,有效范围为1-12的整数或JAN-DEc
DayofWeek : 可出现", - * / ? L C #"四个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year : 可出现", - * /"四个字符,有效范围为1970-2099年
下面简单举几个例子:
"0 0 12 * * ?" 每天中午十二点触发
"0 15 10 ? * *" 每天早上10:15触发
"0 15 10 * * ?" 每天早上10:15触发
"0 * 14 * * ?" 每天从下午2点开始到2点59分每分钟一次触发
"0 0/5 14 * * ?" 每天从下午2点开始到2:55分结束每5分钟一次触发
"0 0/5 14,18 * * ?" 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发
"0 0-5 14 * * ?" 每天14:00至14:05每分钟一次触发
"0 10,44 14 ? 3 WED" 三月的每周三的14:10和14:44触发
"0 15 10 ? * MON-FRI" 每个周一、周二、周三、周四、周五的10:15触发
* : 表示匹配该域的任意值,比如在秒*, 就表示每秒都会触发事件。;
? : 只能用在每月第几天和星期两个域。表示不指定值,当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”;
- : 表示范围,例如在分域使用5-20,表示从5分到20分钟每分钟触发一次
/ : 表示起始时间开始触发,然后每隔固定时间触发一次,例如在分域使用5/20,则意味着5分,25分,45分,分别触发一次.
, : 表示列出枚举值。例如:在分域使用5,20,则意味着在5和20分时触发一次。
L : 表示最后,只能出现在星期和每月第几天域,如果在星期域使用1L,意味着在最后的一个星期日触发。
W : 表示有效工作日(周一到周五),只能出现在每月第几日域,系统将在离指定日期的最近的有效工作日触发事件。注意一点,W的最近寻找不会跨过月份
LW : 这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
# : 用于确定每个月第几个星期几,只能出现在每月第几天域。例如在1#3,表示某月的第三个星期日。
好了,大概就这么多。spring boot还是有很多功能的。