Springboot集成定时器和多线程异步处理操作
需求:用@schedule标签进行定时处理逻辑,由于业务处理速度慢,需要每次执行逻辑放在不同的线程里异步执行
springboot集成多线程异步,直接上配置:
/** *线程池异步配置 */ @Configuration @EnableAsync publicclassThreadExecutorConfig implementsAsyncConfigurer{ @Override publicExecutorgetAsyncExecutor(){ ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor(); //设置核心线程数 executor.setCorePoolSize(5); //设置最大线程数 executor.setMaxPoolSize(7); //设置队列容量 executor.setQueueCapacity(20); //设置线程活跃时间(秒) executor.setKeepAliveSeconds(60); //设置默认线程名称 executor.setThreadNamePrefix("PASCAL-"); //设置拒绝策略 executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy()); //等待所有任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown(true); executor.initialize(); returnexecutor; } @Override publicAsyncUncaughtExceptionHandlergetAsyncUncaughtExceptionHandler(){ returnnewMyAsyncUncaughtExceptionHandler(); } }
下面的是对多线程异步的时候报出的异常处理方法,可以自定义一个处理多线程异常类来实现自身的业务逻辑.
importorg.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; importjava.lang.reflect.Method; publicclassMyAsyncUncaughtExceptionHandlerimplements AsyncUncaughtExceptionHandler{ @Override publicvoidhandleUncaughtException(Throwableex, Methodmethod,Object...params){ //handleexception } }
启动类上要记得添加异步和开启定时器的标签
@SpringBootApplication @EnableScheduling @Async publicclassMultithreadingApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(MultithreadingApplication.class,args); } }
业务逻辑方法:
@Async @Scheduled(initialDelay=1000,fixedDelay=5000) publicvoidtest(){ SimpleDateFormatformat=newSimpleDateFormat("HH:mm:ss"); try{ logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(newDate())); Thread.sleep(10000); logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(newDate())); }catch(InterruptedExceptione){ e.printStackTrace(); } }
对于@Schedule注解的使用方法:
点进去可以看到有几个可选参数:
fixedDelay:控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次
fixedRate:是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。
initialDelay:如:@Scheduled(initialDelay=10000,fixedRate=15000
这个定时器就是在上一个的基础上加了一个initialDelay=10000意思就是在容器启动后,延迟10秒后再执行一次定时器,以后每15秒再执行一次该定时器.
cron表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。
这里可以根据自身的业务需求,看到底选择哪一个更适合,这里cron表达式就不再多言,可以结合自身应用场景来定
这样,需求就实现了
测试结果:
20-07-0711:12:40.436INFO32360---[main]o.s.b.w.embedded.tomcat.TomcatWebServer:Tomcatstartedonport(s):8081(http)withcontextpath'' 2020-07-0711:12:40.444INFO32360---[main]c.e.m.MultithreadingApplication:StartedMultithreadingApplicationin1.223seconds(JVMrunningfor1.739) 2020-07-0711:12:41.445INFO32360---[scheduling-1]o.s.s.concurrent.ThreadPoolTaskExecutor:InitializingExecutorService 2020-07-0711:12:41.452INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法开始时间为:11:12:41 2020-07-0711:12:46.448INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法开始时间为:11:12:46 2020-07-0711:12:51.450INFO32360---[PASCAL-3]c.e.multithreading.service.TestService:当前线程为:PASCAL-3,方法开始时间为:11:12:51 2020-07-0711:12:51.453INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法结束时间为:11:12:51 2020-07-0711:12:56.449INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法结束时间为:11:12:56 2020-07-0711:12:56.450INFO32360---[PASCAL-4]c.e.multithreading.service.TestService:当前线程为:PASCAL-4,方法开始时间为:11:12:56 2020-07-0711:13:01.450INFO32360---[PASCAL-3]c.e.multithreading.service.TestService:当前线程为:PASCAL-3,方法结束时间为:11:13:01 2020-07-0711:13:01.452INFO32360---[PASCAL-5]c.e.multithreading.service.TestService:当前线程为:PASCAL-5,方法开始时间为:11:13:01 2020-07-0711:13:06.451INFO32360---[PASCAL-4]c.e.multithreading.service.TestService:当前线程为:PASCAL-4,方法结束时间为:11:13:06 2020-07-0711:13:06.453INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法开始时间为:11:13:06 2020-07-0711:13:11.453INFO32360---[PASCAL-5]c.e.multithreading.service.TestService:当前线程为:PASCAL-5,方法结束时间为:11:13:11 2020-07-0711:13:11.455INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法开始时间为:11:13:11 2020-07-0711:13:16.453INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法结束时间为:11:13:16 2020-07-0711:13:16.455INFO32360---[PASCAL-3]c.e.multithreading.service.TestService:当前线程为:PASCAL-3,方法开始时间为:11:13:16 2020-07-0711:13:21.456INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法结束时间为:11:13:21 2020-07-0711:13:21.457INFO32360---[PASCAL-4]c.e.multithreading.service.TestService:当前线程为:PASCAL-4,方法开始时间为:11:13:21 2020-07-0711:13:26.456INFO32360---[PASCAL-3]c.e.multithreading.service.TestService:当前线程为:PASCAL-3,方法结束时间为:11:13:26 2020-07-0711:13:26.457INFO32360---[PASCAL-5]c.e.multithreading.service.TestService:当前线程为:PASCAL-5,方法开始时间为:11:13:26 2020-07-0711:13:31.458INFO32360---[PASCAL-4]c.e.multithreading.service.TestService:当前线程为:PASCAL-4,方法结束时间为:11:13:31 2020-07-0711:13:31.459INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法开始时间为:11:13:31 2020-07-0711:13:36.458INFO32360---[PASCAL-5]c.e.multithreading.service.TestService:当前线程为:PASCAL-5,方法结束时间为:11:13:36 2020-07-0711:13:36.460INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法开始时间为:11:13:36 2020-07-0711:13:41.459INFO32360---[PASCAL-1]c.e.multithreading.service.TestService:当前线程为:PASCAL-1,方法结束时间为:11:13:41 2020-07-0711:13:41.462INFO32360---[PASCAL-3]c.e.multithreading.service.TestService:当前线程为:PASCAL-3,方法开始时间为:11:13:41 2020-07-0711:13:46.461INFO32360---[PASCAL-2]c.e.multithreading.service.TestService:当前线程为:PASCAL-2,方法结束时间为:11:13:46
每隔五秒执行一次
-----------------------分割线-----------------------
如果有多个定时任务,每个任务需要在不同的线程间处理的话,就要用另外的配置:如下:
/** *配置多个schedule的线程配置 */ @Configuration @EnableScheduling publicclassScheduleConfigimplementsSchedulingConfigurer{ /* *并行任务 */ publicvoidconfigureTasks(ScheduledTaskRegistrartaskRegistrar) { ThreadPoolTaskSchedulertaskScheduler=newThreadPoolTaskScheduler(); taskScheduler.setThreadNamePrefix("Schedule-Task-"); taskScheduler.setPoolSize(5); taskScheduler.setAwaitTerminationSeconds(60); taskScheduler.setWaitForTasksToCompleteOnShutdown(true); taskScheduler.initialize(); taskRegistrar.setTaskScheduler(taskScheduler); } }
业务如下:
@Scheduled(cron="*/5****?") publicvoidtest1(){ SimpleDateFormatformat=newSimpleDateFormat("HH:mm:ss"); try{ logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(newDate())); Thread.sleep(10000); logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(newDate())); }catch(InterruptedExceptione){ e.printStackTrace(); } } @Scheduled(cron="*/5****?") publicvoidtest2(){ SimpleDateFormatformat=newSimpleDateFormat("HH:mm:ss"); try{ logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(newDate())); Thread.sleep(10000); logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(newDate())); }catch(InterruptedExceptione){ e.printStackTrace(); } }
测试结果:
2020-07-0711:34:53.101INFO27440---[main]c.e.m.MultithreadingApplication:StartedMultithreadingApplicationin1.147seconds(JVMrunningfor1.74) 2020-07-0711:34:55.002INFO27440---[Schedule-Task-2]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-2,方法开始时间为:11:34:55 2020-07-0711:34:55.002INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法开始时间为:11:34:55 2020-07-0711:35:05.003INFO27440---[Schedule-Task-2]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-2,方法结束时间为:11:35:05 2020-07-0711:35:05.003INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法结束时间为:11:35:05 2020-07-0711:35:10.001INFO27440---[Schedule-Task-2]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-2,方法开始时间为:11:35:10 2020-07-0711:35:10.001INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法开始时间为:11:35:10 2020-07-0711:35:20.001INFO27440---[Schedule-Task-2]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-2,方法结束时间为:11:35:20 2020-07-0711:35:20.002INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法结束时间为:11:35:20 2020-07-0711:35:25.001INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法开始时间为:11:35:25 2020-07-0711:35:25.003INFO27440---[Schedule-Task-3]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-3,方法开始时间为:11:35:25 2020-07-0711:35:35.001INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法结束时间为:11:35:35 2020-07-0711:35:35.003INFO27440---[Schedule-Task-3]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-3,方法结束时间为:11:35:35 2020-07-0711:35:40.002INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法开始时间为:11:35:40 2020-07-0711:35:40.002INFO27440---[Schedule-Task-5]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-5,方法开始时间为:11:35:40 2020-07-0711:35:50.002INFO27440---[Schedule-Task-1]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-1,方法结束时间为:11:35:50 2020-07-0711:35:50.002INFO27440---[Schedule-Task-5]c.e.multithreading.service.TestService:当前线程为:Schedule-Task-5,方法结束时间为:11:35:50
以上这篇Springboot集成定时器和多线程异步处理操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。