springboot 定时任务@Scheduled 和 异步@Async

您所在的位置:网站首页 async使用 springboot 定时任务@Scheduled 和 异步@Async

springboot 定时任务@Scheduled 和 异步@Async

2023-10-29 01:32| 来源: 网络整理| 查看: 265

使用@EnableScheduling开启功能

@Configuration @EnableScheduling public class ScheduleConfig { }

编写任务

@Component public class ScheduledTasks { //表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms; @Scheduled(fixedDelay = 500) public void fixedDelay(){ } //表示按一定的频率执行任务,参数类型为long,单位ms; @Scheduled(fixedRate = 500) public void fixedRate(){ } //cron表达式,指定任务在特定时间执行; @Scheduled(cron="0 50 * * * ?") public void cron(){ } //第一次1秒后执行,当执行完后2秒再执行 @Scheduled(initialDelay = 1000, fixedDelay = 2000) public void initialDelay() { } // 可以从配置文件中读取 @Scheduled(fixedDelayString = "${jobs.fixedDelay}") public void fixedDelayString() { } /** * cron:cron表达式,指定任务在特定时间执行; * fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms; * fixedDelayString:与fixedDelay含义一样,只是参数类型变为String; * fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms; * fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String; * initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms; * initialDelayString:与initialDelay的含义一样,只是将参数类型变为String; */ }

配置(可选)

@Configuration public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer{ //并行任务 public void configureTasks(ScheduledTaskRegistrar taskRegistrar){ TaskScheduler taskScheduler = taskScheduler(); taskRegistrar.setTaskScheduler(taskScheduler); } //并行任务使用策略:多线程处理(配置线程数等) @Bean public ThreadPoolTaskScheduler taskScheduler(){ ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(20); scheduler.setThreadNamePrefix("task-"); //设置线程名开头 scheduler.setAwaitTerminationSeconds(60); scheduler.setWaitForTasksToCompleteOnShutdown(true); return scheduler; } //异步任务 public Executor getAsyncExecutor(){ Executor executor = taskScheduler(); return executor; } //异步任务 异常处理 public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){ return new SimpleAsyncUncaughtExceptionHandler(); } }

定时任务线程池中,不管配置多少个线程,每次到定时点,只有一个线程去执行任务。假如配置fixedDelay=500,表示上一次任务执行完后,延迟500毫秒执行下次任务。如果任务执行需要500毫秒,那么任务的执行周期是500+500=1000毫秒。就算线程池中有多个线程,也会等那个任务执行完再选取一个线程再次执行任务。

@Bean("aaa") public TaskScheduler scheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("a"); scheduler.setPoolSize(4); scheduler.initialize(); return scheduler; } @Scheduled(fixedDelay = 500) public void scheduled(){ try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info(Thread.currentThread().getName()); } 2018-10-11 10:18:44.705 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:45.710 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:46.714 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:47.715 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:48.716 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:49.719 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:50.720 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:51.722 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:52.723 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:53.724 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:54.725 com.demo.test.async.ScheduleService : a1 2018-10-11 10:18:55.726 com.demo.test.async.ScheduleService : a3 2018-10-11 10:18:56.727 com.demo.test.async.ScheduleService : a3 2018-10-11 10:18:57.729 com.demo.test.async.ScheduleService : a3

加入配置fixedRate = 500,表示每500毫秒执行一次任务。如果任务执行时间大于配置的值,则任务执行完毕立即执行下一个任务。

@Bean("aaa") public TaskScheduler scheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("a"); scheduler.setPoolSize(4); scheduler.initialize(); return scheduler; } @Scheduled(fixedRate = 500) public void scheduled(){ LOGGER.info(Thread.currentThread().getName()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } 2018-10-11 11:01:21.218 com.demo.test.async.ScheduleService : a1 2018-10-11 11:01:23.219 com.demo.test.async.ScheduleService : a2 2018-10-11 11:01:25.220 com.demo.test.async.ScheduleService : a1 2018-10-11 11:01:27.221 com.demo.test.async.ScheduleService : a1 2018-10-11 11:01:29.221 com.demo.test.async.ScheduleService : a1 2018-10-11 11:01:31.222 com.demo.test.async.ScheduleService : a4 2018-10-11 11:01:33.223 com.demo.test.async.ScheduleService : a4 可以看到任务执行时间是2秒,大于配置500毫秒,所以任务执行完立即执行下一个任务。相当于执行周期变成了任务执行时间。

如果同时开启了@EnableAsync和使用了@Async,便变成了按配置时间(T),每T执行一次任务。如果任务执行时间大于T,则会选取线程池中其他的线程去执行任务,如果没有剩余线程,则会等待有线程空闲出来。

@EnableAsync @Configuration public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setTaskScheduler( scheduler()); } @Bean("aaa") public TaskScheduler scheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("a"); scheduler.setPoolSize(4); scheduler.initialize(); return scheduler; } } @Async("aaa") @Scheduled(fixedRate = 500) public void scheduled(){ LOGGER.info(Thread.currentThread().getName()); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } 2018-10-11 11:12:35.326 com.demo.test.async.ScheduleService : a4 2018-10-11 11:12:35.830 com.demo.test.async.ScheduleService : a2 2018-10-11 11:12:36.338 com.demo.test.async.ScheduleService : a1 2018-10-11 11:12:36.830 com.demo.test.async.ScheduleService : a3 2018-10-11 11:12:37.326 com.demo.test.async.ScheduleService : a4 2018-10-11 11:12:37.836 com.demo.test.async.ScheduleService : a2 2018-10-11 11:12:38.338 com.demo.test.async.ScheduleService : a1 2018-10-11 11:12:38.830 com.demo.test.async.ScheduleService : a3 使用@EnableScheduling,同时不使用@EnableAsync和taskRegistrar也没有添加线程池,这时候执行定时任务,会使用默认的线程池(只有一个线程),多个任务同步执行 @Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { } } @Scheduled(fixedRate = 500) public void scheduled(){ LOGGER.info(Thread.currentThread().getName() + " -- aaa"); } @Scheduled(fixedDelay = 1000) public void fileProcessScheduled(){ LOGGER.info(Thread.currentThread().getName() + " -- bbb"); } 2018-10-12 09:28:32.415 com.demo.test.async.ScheduleService : pool-1-thread-1 -- aaa 2018-10-12 09:28:32.429 com.demo.test.async.ScheduleService : pool-1-thread-1 -- bbb 2018-10-12 09:28:32.915 com.demo.test.async.ScheduleService : pool-1-thread-1 -- aaa 2018-10-12 09:28:33.415 com.demo.test.async.ScheduleService : pool-1-thread-1 -- aaa 2018-10-12 09:28:33.431 com.demo.test.async.ScheduleService : pool-1-thread-1 -- bbb 2018-10-12 09:28:33.915 com.demo.test.async.ScheduleService : pool-1-thread-1 -- aaa 使用@EnableScheduling,同时不使用@EnableAsync,然后在taskRegistrar添加指定线程池,这时候执行定时任务,会使用我们添加的线程池,多个任务同步执行 @Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setTaskScheduler(scheduler()); } @Bean public TaskScheduler scheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("a"); scheduler.setPoolSize(3); scheduler.initialize(); return scheduler; } } @Scheduled(fixedRate = 500) public void scheduled(){ LOGGER.info(Thread.currentThread().getName() + " -- aaa"); } @Scheduled(fixedDelay = 1000) public void fileProcessScheduled(){ LOGGER.info(Thread.currentThread().getName() + " -- bbb"); } 2018-10-12 09:38:09.763 com.demo.test.async.ScheduleService : a2 -- aaa 2018-10-12 09:38:10.265 com.demo.test.async.ScheduleService : a2 -- aaa 2018-10-12 09:38:10.276 com.demo.test.async.ScheduleService : a1 -- bbb 2018-10-12 09:38:10.764 com.demo.test.async.ScheduleService : a3 -- aaa 2018-10-12 09:38:11.264 com.demo.test.async.ScheduleService : a3 -- aaa 2018-10-12 09:38:11.276 com.demo.test.async.ScheduleService : a2 -- bbb 2018-10-12 09:38:11.764 com.demo.test.async.ScheduleService : a1 -- aaa 使用@EnableScheduling和@EnableAsync,然后在任务上用@Async("xxx")指定线程池,taskRegistrar添加不添加线程池无影响,会使用指定的,不会用registrar里添加的,这时候执行定时任务,会使用各自指定的线程池,多个任务(非一个线程池)并行执行 @EnableAsync @Configuration @EnableScheduling public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { } @Bean("aaa") public TaskScheduler a() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("a"); scheduler.setPoolSize(3); scheduler.initialize(); return scheduler; } @Bean("bbb") public TaskScheduler fileProcessScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix("b"); scheduler.setPoolSize(2); scheduler.initialize(); return scheduler; } } @Async("aaa") @Scheduled(fixedRate = 500) public void scheduled(){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } LOGGER.info(Thread.currentThread().getName() + " -- aaa"); } @Async("bbb") @Scheduled(fixedDelay = 1000) public void fileProcessScheduled(){ LOGGER.info(Thread.currentThread().getName() + " -- bbb"); } 2018-10-12 09:43:54.484 com.demo.test.async.ScheduleService : a2 -- aaa 2018-10-12 09:43:54.498 com.demo.test.async.ScheduleService : b2 -- bbb 2018-10-12 09:43:54.985 com.demo.test.async.ScheduleService : a3 -- aaa 2018-10-12 09:43:55.484 com.demo.test.async.ScheduleService : a1 -- aaa 2018-10-12 09:43:55.498 com.demo.test.async.ScheduleService : b1 -- bbb 2018-10-12 09:43:55.984 com.demo.test.async.ScheduleService : a2 -- aaa 2018-10-12 09:43:56.485 com.demo.test.async.ScheduleService : a3 -- aaa 2018-10-12 09:43:56.498 com.demo.test.async.ScheduleService : b2 -- bbb 2018-10-12 09:43:56.984 com.demo.test.async.ScheduleService : a1 -- aaa


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3