Springboot集成定时器和多线程异步处理操作

网友投稿 221 2022-11-19


Springboot集成定时器和多线程异步处理操作

需求:用@schedule标签进行定时处理逻辑,由于业务处理速度慢,需要每次执行逻辑放在不同的线程里异步执行

springboot集成多线程异步,直接上配置:

/**

* 线程池异步配置

*/

@Configuration

@EnableAsync

public class ThreadExecutorConfig

implements AsyncConfigurer {

@Override

public Executor getAsyncExecutor() {

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

// 设置核心线程数

executor.setCorePoolSize(5);

// 设置最大线程数

executor.setMaxPoolSize(7);

// 设置队列容量

executor.setQueueCapacity(20);

// 设置线程活跃时间(秒)

executor.setKeepAliveSeconds(60);

// 设置默认线程名称

executor.setThreadNamePrefix("PASCAL-");

// 设置拒绝策略

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

// 等待所有任务结束后再关闭线程池

executor.setWaitForTasksToCompleteOnShutdown(true);

executor.initialize();

return executor;

}

@Override

public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

return new MyAsyncUncaughtExceptionHandler();

}

}

下面的是对多线程异步的时候报出的异常处理方法,可以自定义一个处理多线程异常类来实现自身的业务逻辑.

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;

import java.lang.reflect.Method;

public class MyAsyncUncaughtExceptionHandler implements

AsyncUncaughtExceptionHandler {

@Override

public void handleUncaughtException(Throwable ex,

Method method, Object... params) {

// handle exception

}

}

启动类上要记得添加异步和开启定时器的标签

@SpringBootApplication

@EnableScheduling

@Async

public class MultithreadingApplication {

public static void main(String[] args) {

SpringApplication.run(MultithreadingApplication.class, args);

}

}

业务逻辑方法:

@Async

@Scheduled(initialDelay=1000,fixedDelay = 5000)

public void test(){

SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");

try {

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));

Thread.sleep(10000);

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

对于@Schedule注解的使用方法:

点进去可以看到有几个可选参数:

fixedDelay:控制方法执行的间隔时间,是以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次

fixedRate:是按照一定的速率执行,是从上一次方法执行开始的时间算起,如果上一次方法阻塞住了,下一次也是不会执行,但是在阻塞这段时间内累计应该执行的次数,当不再阻塞时,一下子把这些全部执行掉,而后再按照固定速率继续执行。

initialDelay:如: @Scheduled(initialDelay = 10000,fixedRate = 15000

这个定时器就是在上一个的基础上加了一个initialDelay = 10000 意思就是在容器启动后,延迟10秒后再执行一次定时器,以后每15秒再执行一次该定时器.

cron表达式可以定制化执行任务,但是执行的方式是与fixedDelay相近的,也是会按照上一次方法结束时间开始算起。

这里可以根据自身的业务需求,看到底选择哪一个更适合,这里cron表达式就不再多言,可以结合自身应用场景来定

这样,需求就实现了

测试结果:

20-07-07 11:12:40.436 INFO 32360 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (hsMvLhjHnpttp) with context path ''

2020-07-07 11:12:40.444 INFO 32360 --- [ main] c.e.m.MultithreadingApplication : Started MultithreadingApplication in 1.223 seconds (JVM running for 1.739)

2020-07-07 11:12:41.445 INFO 32360 --- [ scheduling-1] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService

2020-07-07 11:12:41.452 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法开始时间为:11:12:41

2020-07-07 11:12:46.448 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法开始时间为:11:12:46

2020-07-07 11:12:51.450 INFO 32360 --- [ PASCAL-3] c.e.multithreading.service.TestService : 当前线程为:PASCAL-3,方法开始时间为:11:12:51

2020-07-07 11:12:51.453 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法结束时间为:11:12:51

2020-07-07 11:12:56.449 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法结束时间为:11:12:56

2020-07-07 11:12:56.450 INFO 32360 --- [ PASCAL-4] c.e.multithreading.service.TestService : 当前线程为:PASCAL-4,方法开始时间为:11:12:56

2020-07-07 11:13:01.450 INFO 32360 --- [ PASCAL-3] c.e.multithreading.service.TestService : 当前线程为:PASCAL-3,方法结束时间为:11:13:01

2020-07-07 11:13:01.452 INFO 32360 --- [ PASCAL-5] c.e.multithreading.service.TestService : 当前线程为:PASCAL-5,方法开始时间为:11:13:01

2020-07-07 11:13:06.451 INFO 32360 --- [ PASCAL-4] c.e.multithreading.service.TestService : 当前线程为:PASCAL-4,方法结束时间为:11:13:06

2020-07-07 11:13:06.453 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法开始时间为:11:13:06

2020-07-07 11:13:11.453 INFO 32360 --- [ PASCAL-5] c.e.multithreading.service.TestService : 当前线程为:PASCAL-5,方法结束时间为:11:13:11

2020-07-07 11:13:11.455 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法开始时间为:11:13:11

2020-07-07 11:13:16.453 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法结束时间为:11:13:16

2020-07-07 11:13:16.455 INFO 32360 --- [ PASCAL-3] c.e.multithreading.service.TestService : 当前线程为:PASCAL-3,方法开始时间为:11:13:16

2020-07-07 11:13:21.456 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法结束时间为:11:13:21

2020-07-07 11:13:21.457 INFO 32360 --- [ PASCAL-4] c.e.multithreading.service.TestService : 当前线程为:PASCAL-4,方法开始时间为:11:13:21

2020-07-07 11:13:26.456 INFO 32360 --- [ PASCAL-3] c.e.multithreading.service.TestService : 当前线程为:PASCAL-3,方法结束时间为:11:13:26

2020-07-07 11:13:26.457 INFO 32360 --- [ PASCAL-5] c.e.multithreading.service.TestService : 当前线程为:PASCAL-5,方法开始时间为:11:13:26

2020-07-07 11:13:31.458 INFO 32360 --- [ PASCAL-4] c.e.multithreading.service.TestService : 当前线程为:PASCAL-4,方法结束时间为:11:13:31

2020-07-07 11:13:31.459 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法开始时间为:11:13:31

2020-07-07 11:13:36.458 INFO 32360 --- [ PASCAL-5] c.e.multithreading.service.TestService : 当前线程为:PASCAL-5,方法结束时间为:11:13:36

2020-07-07 11:13:36.460 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法开始时间为:11:13:36

2020-07-07 11:13:41.459 INFO 32360 --- [ PASCAL-1] c.e.multithreading.service.TestService : 当前线程为:PASCAL-1,方法结束时间为:11:13:41

2020-07-07 11:13:41.462 INFO 32360 --- [ PASCAL-3] c.e.multithreading.service.TestService : 当前线程为:PASCAL-3,方法开始时间为:11:13:41

2020-07-07 11:13:46.461 INFO 32360 --- [ PASCAL-2] c.e.multithreading.service.TestService : 当前线程为:PASCAL-2,方法结束时间为:11:13:46

每隔五秒执行一次

-----------------------分割线-----------------------

如果有多个定时任务,每个任务需要在不同的线程间处理的话,就要用另外的配置:如下:

/**

* 配置多个schedule的线程配置

*/

@Configuration

@EnableScheduling

public class ScheduleConfig implements SchedulingConfigurer{

/*

* 并行任务

*/

public void configureTasks(ScheduledTaskRegistrar taskRegistrar)

{

ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();

taskScheduler.setThreadNamePrefix("Schedule-Task-");

taskScheduler.setPoolSize(5);

taskScheduler.setAwaitTerminationSeconds(60);

taskScheduler.setWaitForTasksToCompleteOnShutdown(true);

taskScheduler.initialize();

taskRegistrar.setTaskScheduler(taskScheduler);

}

}

业务如下:

@Scheduled(cron = "*/5 * * * * ?")

public void test1(){

SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");

try {

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));

Thread.sleep(10000);

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

@Scheduled(cron = "*/5 * * * * ?")

public void test2(){

SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss");

try {

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法开始时间为:"+format.format(new Date()));

Thread.sleep(10000);

logger.info("当前线程为:"+Thread.currentThread().getName()+",方法结束时间为:"+format.format(new Date()));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

测试结果:

2020-07-07 11:34:53.101 INFO 27440 --- [ main] c.e.m.MultithreadingApplication : Started MultithreadingApplication in 1.147 seconds (JVM running for 1.74)

2020-07-07 11:34:55.002 INFO 27440 --- [Schedule-Task-2] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-2,方法开始时间为:11:34:55

2020-07-07 11:34:55.002 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法开始时间为:11:34:55

2020-07-07 11:35:05.003 INFO 27440 --- [Schedule-Task-2] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-2,方法结束时间为:11:35:05

2020-07-07 11:35:05.003 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法结束时间为:11:35:05

2020-07-07 11:35:10.001 INFO 27440 --- [Schedule-Task-2] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-2,方法开始时间为:11:35:10

2020-07-07 11:35:10.001 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法开始时间为:11:35:10

2020-07-07 11:35:20.001 INFO 27440 --- [Schedule-Task-2] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-2,方法结束时间为:11:35:20

2020-07-07 11:35:20.002 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法结束时间为:11:35:20

2020-07-07 11:35:25.001 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法开始时间为:11:35:25

2020-07-07 11:35:25.003 INFO 27440 --- [Schedule-Task-3] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-3,方法开始时间为:11:35:25

2020-07-07 11:35:35.001 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法结束时间为:11:35:35

2020-07-07 11:35:35.003 INFO 27440 --- [Schedule-Task-3] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-3,方法结束时间为:11:35:35

2020-07-07 11:35:40.002 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法开始时间为:11:35:40

2020-07-07 11:35:40.002 INFO 27440 --- [Schedule-Task-5] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-5,方法开始时间为:11:35:40

2020-07-07 11:35:50.002 INFO 27440 --- [Schedule-Task-1] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-1,方法结束时间为:11:35:50

2020-07-07 11:35:50.002 INFO 27440 --- [Schedule-Task-5] c.e.multithreading.service.TestService : 当前线程为:Schedule-Task-5,方法结束时间为:11:35:50


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java定时任务实现的4种方式小结
下一篇:Spring Task定时任务每天零点执行一次的操作
相关文章

 发表评论

暂时没有评论,来抢沙发吧~