Springboot 线程池配置

最近的项目里要手动维护线程池,然后看到一起开发的小伙伴直接用Java了,我坚信Springboot不可能没这功能,于是查了些资料,果然有,这里给一下。

首先我们都知道@Async标签能让方法异步执行,但是这个标签用的是Springboot默认的线程池,想自己实现线程池就要在项目里创建一个TaskExecutor或它的子类的Bean,像这样:

    @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里提供了四种默认的策略,非常粗暴:

    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对其进行配置:

@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

以上。

posted @ 2018-05-18 12:22  CieloSun  阅读(6877)  评论(0编辑  收藏  举报