Springboot 線程池配置

最近的項目裏要手動維護線程池,而後看到一塊兒開發的小夥伴直接用Java了,我堅信Springboot不可能沒這功能,因而查了些資料,果真有,這裏給一下。java

首先咱們都知道@Async標籤能讓方法異步執行,可是這個標籤用的是Springboot默認的線程池,想本身實現線程池就要在項目裏建立一個TaskExecutor或它的子類的Bean,像這樣:less

@Bean
    public AsyncTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor=new ThreadPoolTaskExecutor();
        //加入此頭後此線程池成爲系統線程池
        threadPoolTaskExecutor.setThreadNamePrefix("Anno-Executor");
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }

其中拒絕策略能夠改成手動編寫,像下面這樣:異步

threadPoolTaskExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                
            }
        });

JDK裏提供了四種默認的策略,很是粗暴:ide

public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
         */
        public CallerRunsPolicy() { }

        /**
         * Executes task r in the caller's thread, unless the executor
         * has been shut down, in which case the task is discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }

    /**
     * A handler for rejected tasks that throws a
     * {@code RejectedExecutionException}.
     */
    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
         */
        public AbortPolicy() { }

        /**
         * Always throws RejectedExecutionException.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         * @throws RejectedExecutionException always
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
        }
    }

    /**
     * A handler for rejected tasks that silently discards the
     * rejected task.
     */
    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
         */
        public DiscardPolicy() { }

        /**
         * Does nothing, which has the effect of discarding task r.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }

    /**
     * A handler for rejected tasks that discards the oldest unhandled
     * request and then retries {@code execute}, unless the executor
     * is shut down, in which case the task is discarded.
     */
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
         */
        public DiscardOldestPolicy() { }

        /**
         * Obtains and ignores the next task that the executor
         * would otherwise execute, if one is immediately available,
         * and then retries execution of task r, unless the executor
         * is shut down, in which case task r is instead discarded.
         *
         * @param r the runnable task requested to be executed
         * @param e the executor attempting to execute this task
         */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
  • CallerRunsPolicy是讓調用方法的線程本身運行。
  • AbortPolicy丟棄任務拋出異常。
  • DiscardPolicy:丟棄任務不報錯。
  • DiscardOldestPolicy:丟棄隊列最前面任務,以後嘗試執行。

順便說一下,查源碼可知,默認的策略是AbortPolicy,也就是最粗暴的那個,不過考慮到一般是不要讓拒絕發生的,這裏用粗暴的方案問題不大。爲了實現方便配置,能夠用yml對其進行配置:this

@Component
@Data
@ConfigurationProperties("thread-pool-factory")
public class ThreadPoolFactory {
    private int corePoolSize;
    private int maxPoolSize;
    private int queueCapacity;
    private int keepAliveSeconds;
    @Bean
    public AsyncTaskExecutor threadPoolTaskExecutor(){
        //......
    }
}

這裏@Data標籤是lambok的標籤,快速生成getter和setter用。以上Component構建好後,能夠直接配置:線程

thread-pool-factory:
    #IO密集型應用,線程數爲2N+1
    corePoolSize: 9
    maxPoolSize: 18
    queueCapacity: 100
    keepAliveSeconds: 120

以上。code

相關文章
相關標籤/搜索