Java的線程池一般是基於concurrent包下的ThreadPoolExecutor類實現的,
不過當我們基於spring框架開發程序時,
通常會使用其包裝類ThreadPoolTaskExecutor,
這里有一個小問題就是當使用線程池執行任務的時候,
任務的消費速度小於生產速度時,任務通常會被阻塞到阻塞隊列,
而阻塞隊列大小通常是固定的,當阻塞隊列滿的時候,execute方法並不會阻塞,
默認是使用RejectedExecutionHandler去處理拒絕的任務,默認策略是AbortPolicy,直接拋出RejectedExecutionException異常,
很多情況下,這不符合我們的業務需求,我們希望被拒絕的任務能夠阻塞執行,從而阻止任務的生產速度;
一個比較巧妙的解決方案如下,僅供參考,具體還需要根據實際場景來應用:
import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration public class TaskExecutorConfig { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Bean("vgcThreadPoolTaskExecutor") public Executor threadPoolTaskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(6); taskExecutor.setMaxPoolSize(50); taskExecutor.setQueueCapacity(1000); taskExecutor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor executor) -> { if (!executor.isShutdown()) { try { executor.getQueue().put(r); } catch (InterruptedException e) { logger.error(e.toString(), e); Thread.currentThread().interrupt(); } } } ); taskExecutor.initialize(); return taskExecutor; } }
這里之所以能實現阻塞,是基於BlockingQueue的put方法來實現的,當阻塞隊列滿時,put方法會一直等待...