ThreadPoolTaskExecutor 如果執行緒池預設的queue滿了,會觸發什麼異常

gongchengship發表於2024-10-10

Spring 中,使用 ThreadPoolTaskExecutor 時,如果執行緒池中的 任務佇列(Queue) 滿了,預設情況下並不會直接丟擲異常,而是會根據 RejectedExecutionHandler 的策略來決定如何處理被拒絕的任務。ThreadPoolTaskExecutor 繼承自 Java 的 ThreadPoolExecutor,因此它使用了 ThreadPoolExecutor 中定義的拒絕策略來處理這種情況。

RejectedExecutionHandler 的預設策略

ThreadPoolTaskExecutor 使用的底層實現是 ThreadPoolExecutor,它有四種處理拒絕任務的策略,預設情況下使用的是 AbortPolicy。當任務佇列滿時,會觸發 java.util.concurrent.RejectedExecutionException 異常。以下是 ThreadPoolExecutor 支援的四種策略:

  1. AbortPolicy(預設):當任務無法被提交到執行緒池時,會丟擲 RejectedExecutionException
  2. CallerRunsPolicy:當任務無法被提交時,呼叫該任務的執行緒(提交任務的執行緒)會直接執行這個任務。這可能會影響應用程式的效能,因為原本用於提交任務的執行緒現在正在執行任務。
  3. DiscardPolicy:直接丟棄新提交的任務,不丟擲異常。
  4. DiscardOldestPolicy:丟棄佇列中最早提交但尚未被執行的任務,然後重新嘗試提交當前任務。

預設的處理行為

如果 ThreadPoolTaskExecutor 沒有設定自定義的拒絕策略,預設會使用 AbortPolicy,也就是說,當任務佇列滿了之後,會丟擲 RejectedExecutionException。這個異常表明執行緒池已經無法再接受新的任務,因為工作執行緒都已佔用且佇列已滿。

自定義拒絕策略

如果不想讓任務在佇列滿的時候直接丟擲異常,您可以自定義 ThreadPoolTaskExecutor 的拒絕策略。可以透過 setRejectedExecutionHandler() 方法來指定不同的策略。

例如:

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();

這段程式碼將 CallerRunsPolicy 設定為拒絕策略,當佇列滿時,提交任務的執行緒會執行該任務而不是丟擲異常。

結論

ThreadPoolTaskExecutor 中,如果執行緒池的任務佇列滿了,預設情況下會丟擲 RejectedExecutionException,這是由於使用了預設的 AbortPolicy。您可以根據需要自定義拒絕策略以避免異常或選擇其他處理方式。

相關文章