ThreadPoolTaskExecutor线程池管理(解决@Async问题)

ThreadPoolTaskExecutor线程池管理

ThreadPoolTaskExecutor介绍

ThreadPoolTaskExecutor是Spring框架提供的线程池管理器,它继承自ThreadPoolExecutor类,并对其进行了一些扩展和封装。下面是ThreadPoolTaskExecutor的常用参数:

  1. corePoolSize(核心线程数):线程池中保持活动状态的最小线程数。
  2. maxPoolSize(最大线程数):线程池中允许存在的最大线程数,超过该数量的任务会放入等待队列。
  3. keepAliveSeconds(线程活动时间):当线程池中线程数量超过核心线程数时,多余的空闲线程的存活时间。
  4. queueCapacity(等待队列容量):等待队列的容量,用于存放等待执行的任务。
  5. threadNamePrefix(线程名前缀):新创建的线程的名称前缀,默认为task-
  6. rejectedExecutionHandler(拒绝策略):当线程池和等待队列都满了,无法处理新的任务时的处理策略,可选的策略有:
    • AbortPolicy:直接抛出RejectedExecutionException异常,默认策略。
    • CallerRunsPolicy:在调用者的线程中执行该任务。
    • DiscardPolicy:丢弃任务,不抛出异常。
    • DiscardOldestPolicy:丢弃队列中最旧的任务,然后重新尝试执行新的任务。

除了以上常用参数外,ThreadPoolTaskExecutor还提供了一些其他可配置属性和方法来进一步控制线程池的行为。

例如,你可以修改核心线程数、最大线程数和等待队列容量:

executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);

你还可以设置是否允许核心线程超时关闭、是否允许核心线程被回收等高级配置:

executor.setAllowCoreThreadTimeOut(true); // 允许核心线程超时关闭
executor.setWaitForTasksToCompleteOnShutdown(true); // 等待所有任务完成后再关闭线程池
executor.setAwaitTerminationSeconds(60); // 等待终止的时间

这些是ThreadPoolTaskExecutor常用的一些参数和配置选项。根据具体需求,你可以选择合适的参数来配置线程池,以满足你的业务需求。

实现步骤

配置管理器

@Slf4j
@EnableAsync
@Configuration
public class AsyncConfiguration implements AsyncConfigurer {

    @Primary
    @Bean(name = AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME)
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 获取电脑的处理器数量,一般电脑一个处理器有两个逻辑线程
        int num = Runtime.getRuntime().availableProcessors();
        // 核心线程数目 核心线程数最好设置为电脑的逻辑线程总数 + 1,达到最大化利用处理器
        executor.setCorePoolSize(num * 2 + 1);
        // 指定最大线程数
        executor.setMaxPoolSize(200);
        // 队列中最大的数目
        executor.setQueueCapacity(100);
        // 线程名称前缀
        executor.setThreadNamePrefix("taskExecutor-");
        // 拒绝策略:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 当调度器shutdown被调用时等待当前被调度的任务完成
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 线程空闲后的最大存活时间
        executor.setKeepAliveSeconds(60);
        // 线程池初始化
        executor.initialize();
        return executor;
    }

    @Override
    public Executor getAsyncExecutor() {
        return taskExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new CustomAsyncUncaughtExceptionHandler();
    }

    static class CustomAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            log.error(">>> CustomAsyncUncaughtExceptionHandler,class:{}, method: {}, params: {}, error: {}",
                    method.getDeclaringClass().getSimpleName(), method.getName(), Arrays.toString(params),
                    ex.getMessage());
        }
    }

}

测试

@Component
public class MyTask {

    @Async("taskExecutor")
    public void executeAsyncTask() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步方法打印:" + i);
        }
    }
}
@RestController
@RequestMapping("/test")
@Api(tags = "测试")
public class TestController {

    @Autowired
    private MyTask myTask;

    @RequestMapping(value = "/thread", method = RequestMethod.GET)
    public void thread() {
        myTask.executeAsyncTask();
        System.out.println("异步执行成功!");
    }

}

通过在方法上添加@Async("taskExecutor")注解,指定了使用名为"taskExecutor"的线程池来执行异步任务。

这样,你就可以在整个应用程序中使用同一个全局线程池管理器来执行异步任务。确保在需要使用的类上添加@Component或其他适当的注解,以便Spring Boot能够正确地扫描和管理这些组件。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadPoolTaskExecutor不加@Async注解时,主要用于在需要使用线程池的地方实现线程池级别的异步调用。可以通过在代码中引入我们配置的线程池bean,然后调用其execute方法来执行需要在后台进行的长时间操作。例如,在一个@Service类中,我们可以通过@Resource注解引入名为"asyncTaskExecutor"的ThreadPoolTaskExecutor实例,并在需要进行异步操作的方法中使用该线程池执行任务。这样可以确保任务在后台以异步方式执行,而不会阻塞主线程。 另外,如果需要自定义线程池的配置,也可以实现AsyncConfigurer接口,在配置类中重写getAsyncExecutor方法,并返回一个自定义的线程池实例。例如,可以通过在@Configuration类中实现AsyncConfigurer接口,重写getAsyncExecutor方法,并在该方法中创建并返回一个指定大小的线程池实例。这样可以灵活地配置线程池的大小和其他参数,以满足具体的业务需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [简单记录ThreadPoolTaskExecutor线程池和@Async注解](https://blog.csdn.net/zgl971025/article/details/122107575)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Spring 异步@Async注解用法 Spring @Async注解用法总结 Spring @Async基本用法示例](https://blog.csdn.net/HaHa_Sir/article/details/128126282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值