springBoot執行緒池
1:定義執行緒池
1 2 3 4 5 6 7 8 9 10 11 12 13 |
10 );
|
executor.setWaitForTasksToCompleteOnShutdown(
true
);
executor.setAwaitTerminationSeconds(
60
);
1 2 3 |
|
上面我們通過使用ThreadPoolTaskExecutor
建立了一個執行緒池,同時設定了以下這些引數:
- 核心執行緒數10:執行緒池建立時候初始化的執行緒數
- 最大執行緒數20:執行緒池最大的執行緒數,只有在緩衝佇列滿了之後才會申請超過核心執行緒數的執行緒
- 緩衝佇列200:用來緩衝執行任務的佇列
- 允許執行緒的空閒時間60秒:當超過了核心執行緒出之外的執行緒在空閒時間到達之後會被銷燬
- 執行緒池名的字首:設定好了之後可以方便我們定位處理任務所在的執行緒池
- 執行緒池對拒絕任務的處理策略:這裡採用了
CallerRunsPolicy
策略,當執行緒池沒有處理能力的時候,該策略會直接在 execute 方法的呼叫執行緒中執行被拒絕的任務;如果執行程式已關閉,則會丟棄該任務
說明:setWaitForTasksToCompleteOnShutdown(true)
該方法就是這裡的關鍵,用來設定執行緒池關閉的時候等待所有任務都完成再繼續銷燬其他的Bean,這樣這些非同步任務的銷燬就會先於Redis執行緒池的銷燬。同時,這裡還設定了setAwaitTerminationSeconds(60),該方法用來設定執行緒池中任務的等待時間,如果超過這個時候還沒有銷燬就強制銷燬,以確保應用最後能夠被關閉,而不是阻塞住。
2:如何使用該執行緒池呢?
1 2 3 4 5 |
|
@Autowired
private
StringRedisTemplate stringRedisTemplate;
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 |
|
3 執行非同步任務
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
1 2 3 4 5 6 |
|
4 注意事項
注: @Async所修飾的函式不要定義為static型別,這樣非同步呼叫不會生效
從異常信息JedisConnectionException: Could not get a resource from the pool
來看,我們很容易的可以想到,在應用關閉的時候非同步任務還在執行,由於Redis連線池先銷燬了,導致非同步任務中要訪問Redis的操作就報了上面的錯。所以,我們得出結論,上面的實現方式在應用關閉的時候是不優雅的,那麼我們要怎麼做呢?如下設定:
executor.setWaitForTasksToCompleteOnShutdown(
true
);
executor.setAwaitTerminationSeconds(
60
);