定时任务
Posted 517cn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了定时任务相关的知识,希望对你有一定的参考价值。
开启定时任务功能
package com.huang.pims; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @ComponentScan(basePackages = {"com.huang.pims.*"}) @EnableCaching
// 开启定时任务功能 @EnableScheduling public class PimsApplication { public static void main(String[] args) { SpringApplication.run(PimsApplication.class, args); } }
创建定时任务的示例
package com.huang.pims.schedule.tasks; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.Date; @Service public class ScheduledTaskDemo01 { /** * 每分钟内秒数为3的倍数的时间点皆可以执行任务 * 如果因执行上一个任务,而错过了一个多个时间点,则需等待至最近的一个时间点方可以继续执行 * 例如,3,6,9,12,15,18,21等等,这些都是可以执行任务的时间点 * 如果在时间点6执行了一个耗时7s的任务,那么时间点9和时间点12就无法执行任务,必须等到时间点15,才可以执行下次任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 那么, * while(actuallyTime % 3 == 0 && actuallyTime <= nowTime + exeTime) { * actuallyTime += 3; * } * */ @Scheduled(cron = "0/3 * * * * *") public void cronTask() { System.out.println("定时任务:每过3s执行一次任务"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.cronTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(3000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date())); } /** * 周期性延迟执行任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 那么,actuallyTime >= nowTime + exeTime + fixedDelay; */ @Scheduled(fixedDelay = 2000) public void delayTask() { System.out.println("定时任务:执行完一次任务后,先延迟2秒再执行下一次任务"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(1000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date())); } /** * 周期性执行任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 如果 exeTime >= fixedRate ,那么,actuallyTime >= nowTime + exeTime; * 如果 exeTime < fixedRate , 那么,actuallyTime >= nowTime + fixedRate; */ @Scheduled(fixedRate = 2000) public void periodTask() { System.out.println("定时任务:每2秒执行一次"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(3000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 结束时间:" + sdf.format(new Date())); } }
如果想看到效果,直接启动项目即可。从结果可以看出,这些任务都是由同一条线程串行调度的。如果任务较少,还可以接受,但是如果任务很多,任务也很耗时,那就不适合了。这时可以使用@EnableAsync注解来开启对异步事件的支持,@Async来注解定时任务类或方法。这样可以使得,每次执行的任务都将由一条新的线程来执行。如此,可以使用线程池的技术来进一步优化,毕竟无限的创建、销毁线程很消耗性能。
定时任务优化
配置定时任务的线程池
package com.huang.pims; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @SpringBootApplication @ComponentScan(basePackages = {"com.huang.pims.*"}) @EnableCaching @EnableScheduling // 开启定时任务 @EnableAsync // 开启异步支持 public class PimsApplication { public static void main(String[] args) { SpringApplication.run(PimsApplication.class, args); } @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(10);// 核心线程数 taskExecutor.setMaxPoolSize(15);// 最大线程数 taskExecutor.initialize(); return taskExecutor; } }
使用了@Async来注解定时任务类
package com.huang.pims.schedule.tasks; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.Date; @Service @Async public class ScheduledTaskDemo01 { /** * 每分钟内秒数为3的倍数的时间点皆可以执行任务 * 如果因执行上一个任务,而错过了一个多个时间点,则需等待至最近的一个时间点方可以继续执行 * 例如,3,6,9,12,15,18,21等等,这些都是可以执行任务的时间点 * 如果在时间点6执行了一个耗时7s的任务,那么时间点9和时间点12就无法执行任务,必须等到时间点15,才可以执行下次任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 那么, * while(actuallyTime % 3 == 0 && actuallyTime <= nowTime + exeTime) { * actuallyTime += 3; * } * */ @Scheduled(cron = "0/3 * * * * *") public void cronTask() { System.out.println("定时任务:每过3s执行一次任务"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.cronTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(3000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date())); } /** * 周期性延迟执行任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 那么,actuallyTime >= nowTime + exeTime + fixedDelay; */ @Scheduled(fixedDelay = 2000) public void delayTask() { System.out.println("定时任务:执行完一次任务后,先延迟2秒再执行下一次任务"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(1000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.delayTask() 结束时间:" + sdf.format(new Date())); } /** * 周期性执行任务 * * 假设: * 执行一次任务需要消耗的时间为 exeTime * 执行此次任务的开始时间是 nowTime * 执行下一次任务的实际时间是 actuallyTime * 如果 exeTime >= fixedRate ,那么,actuallyTime >= nowTime + exeTime; * 如果 exeTime < fixedRate , 那么,actuallyTime >= nowTime + fixedRate; */ @Scheduled(fixedRate = 2000) public void periodTask() { System.out.println("定时任务:每2秒执行一次"); System.out.println("当前线程:"+Thread.currentThread().getName()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 开始时间:" + sdf.format(new Date())); try { Thread.sleep(3000); } catch (InterruptedException e) {} System.out.println("【定时任务】ScheduledTaskDemo01.periodTask() 结束时间:" + sdf.format(new Date())); } }
开启项目,即可看到定时任务的效果。
以上是关于定时任务的主要内容,如果未能解决你的问题,请参考以下文章