项目环境说明:
- 基于springboot 2.1.0版
- jdk1.8
- 开发工具IDEA
基于Scheduled的定时任务
基于Scheduled的定时任务,在实现了一个简单的定时任务之后,发现使用起来是非常的方便快捷。
一个简单的定时任务
第一步:在启动类上添加注解:@EnableScheduling
@SpringBootApplication
@ServletComponentScan
@EnableScheduling
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}
第二步:创建一个定时任务类:在要执行的方法上通过@Scheduled(cron = "0/5 * * * * ?") 进行定时执行操作
@Component
public class TestTask {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(cron = "0/5 * * * * ?")
public void test1() {
System.out.println("测试定时任务" + dateFormat.format(new Date()));
}
}
第三步:请启动项目,查看控制台结果
到这里一个简单的定时任务就完成了。
关于几个注解的简单说明:
@EnableScheduling 表示开启springboot对定时任务的支持
@Component 表示spring管理的组件。
@Scheduled 表示定时任务, 通过对于的参数可以设定定时任务的执行时间
cron :按照cron表达式执行 cron 表达式自动生成网站:http://cron.qqe2.com/
fixedRate :按照一定间隔时间执行
fixedDelay :按照时间间隔执行和fixedRate有区别 fixedRate 任务两次执行时间间隔是任务的开始点,而 fixedDelay 的间隔是前次任务的结束与下次任务的开始。
单线程和多线程执行定时任务
本来是没有注意到这个问题的,但是在学习的时候浏览网上的资料发现很多关于单线程和多线程执行的问题。因此也一并记录下来。
单线程定时任务
第一步:在上面简单定时任务的代码上,创建多个定时任务,并打印出任务执行日志查看任务执行的线程信息。
@Component
public class TestTask {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
protected Logger logger = LoggerFactory.getLogger(getClass());
@Scheduled(cron = "0/5 * * * * ?")
public void test1() {
logger.error("测试定时任务" + dateFormat.format(new Date()));
}
@Scheduled(cron = "0/5 * * * * ?")
public void test2() {
logger.error("测试定时任务222222222222" + dateFormat.format(new Date()));
}
@Scheduled(cron = "0/5 * * * * ?")
public void test3() {
logger.error("测试定时任务33333333333333" + dateFormat.format(new Date()));
}
@Scheduled(cron = "0/5 * * * * ?")
public void test4() {
logger.error("测试定时任务444444444" + dateFormat.format(new Date()));
}
}
第二步:启动项目查看日志信息
在上图可以看见所有的定时任务都是同一个线程执行的,但是定时任务的执行顺序却是随机的。
第三步:测试如果其中一个任务出错或者执行时间过长会有怎样的效果 修改test2方法代码如下:
@Scheduled(cron = "0/5 * * * * ?")
public void test2() {
logger.error("测试定时任务222222222222" + dateFormat.format(new Date()));
try {
//模拟执行时间过长
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(1/0);
}
结果如下:
单线程执行结果
在执行多个定时任务时,不进行额外配置的话,默认是单线程执行,并且定时任务的执行顺序是随机的,如果其中某个任务出错,不影响后续的定时任务执行,但是如果某个定时任务执行时间过长,或者卡死,则会导致后面的定时任务无法执行。
多线程定时任务
第一步:创建一个配置类配置线程池大小
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//设置线程池大小
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}
第二步:直接启动程序查看结果
多线程执行结果
通过配置类设置一个线程池可以让多个定时任务在不同线程当中执行,执行顺序是随机的,并且相互独立。
总的来说,简单方便,上手容易。能够处理大部分的定时任务需求,但是例如:某个定时任务执行一段时间后,不需要了,或者执行时间要修改就比较不方便。