需求:用@schedule標簽進行定時處理邏輯,由于業務處理速度慢,需要每次執行邏輯放在不同的線程里異步執行
springboot集成多線程異步,直接上配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/** * 線程池異步配置 */ @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(); } } |
下面的是對多線程異步的時候報出的異常處理方法,可以自定義一個處理多線程異常類來實現自身的業務邏輯.
1
2
3
4
5
6
7
8
9
10
11
|
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 } } |
啟動類上要記得添加異步和開啟定時器的標簽
1
2
3
4
5
6
7
8
9
|
@SpringBootApplication @EnableScheduling @Async public class MultithreadingApplication { public static void main(String[] args) { SpringApplication.run(MultithreadingApplication. class , args); } } |
業務邏輯方法:
1
2
3
4
5
6
7
8
9
10
11
12
|
@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表達式就不再多言,可以結合自身應用場景來定
這樣,需求就實現了
測試結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
20 - 07 - 07 11 : 12 : 40.436 INFO 32360 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) 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 |
每隔五秒執行一次
-----------------------分割線-----------------------
如果有多個定時任務,每個任務需要在不同的線程間處理的話,就要用另外的配置:如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 配置多個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); } } |
業務如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@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(); } } |
測試結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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 |
以上這篇Springboot集成定時器和多線程異步處理操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/weixin_43469563/article/details/107176629