ThreadPoolTaskExecutor @Async

https://www.cnblogs.com/zjdxr-up/p/15835364.html

1. 使用 ThreadPoolTaskExecutor  封装自定义配置的线程池Bean

  ThreadPoolTaskExecutor 是Spring 中封装的一个类,spring boot中常用 ThreadPoolTaskExecutor 创建线程池,并把它注入到 IOC 容器中,从而可以全局进行使用。

   如下为使用 ThreadPoolTaskExecutor  创建的自定义配置的 线程池类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
@EnableAsync
public class ThreadPoolExecutorConfig {

    @Bean(name="threadPoolExecutor")
    public Executor threadPoolExecutor(){
        ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
        int processNum = Runtime.getRuntime().availableProcessors(); // 返回可用处理器的Java虚拟机的数量
        int corePoolSize = (int) (processNum / (1 - 0.2));
        int maxPoolSize = (int) (processNum / (1 - 0.5));
        threadPoolExecutor.setCorePoolSize(corePoolSize); // 核心池大小
        threadPoolExecutor.setMaxPoolSize(maxPoolSize); // 最大线程数
        threadPoolExecutor.setQueueCapacity(maxPoolSize * 1000); // 队列程度
        threadPoolExecutor.setThreadPriority(Thread.MAX_PRIORITY);
        threadPoolExecutor.setDaemon(false);
        threadPoolExecutor.setKeepAliveSeconds(300);// 线程空闲时间
        threadPoolExecutor.setThreadNamePrefix("test-Executor-"); // 线程名字前缀
        return threadPoolExecutor;
    }
}

  @EnableAsync是与@Async配合使用,用于执行异步任务

  使用示例:

@Service
public class SpringExecutorTest {
    @Autowired
    private Executor threadPoolExecutor;

    public void test(){
        AtomicInteger num = new AtomicInteger(0);
        for (int i = 0; i < 5; i++) {
            threadPoolExecutor.execute(()->{
                num.incrementAndGet();
            });
        }
        System.out.println(num.get());
    }
}

2. 与 @Async 注解使用

    @Async("threadPoolExecutor")
    public void asyncTest(){
        log.error("threadPoolExecutor asyncTest start");
    }

  需要注意的是,在使用 @Async 注解时,想使用自定义的 Executor 线程池配置,则需要在 @Async 注解上声明线程池的名称,否则会使用默认的线程池配置。

  若想在使用@Async 注解时,不显示声明线程池,且使用定义线程池的配置,可采用以下方式进行配置:

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;

@Slf4j
@Configuration
public class NativeAsyncTaskExecutePool implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
        int processNum = Runtime.getRuntime().availableProcessors(); // 返回可用处理器的Java虚拟机的数量
        int corePoolSize = (int) (processNum / (1 - 0.2));
        int maxPoolSize = (int) (processNum / (1 - 0.5));
        threadPoolExecutor.setCorePoolSize(corePoolSize); // 核心池大小
        threadPoolExecutor.setMaxPoolSize(maxPoolSize); // 最大线程数
        threadPoolExecutor.setQueueCapacity(maxPoolSize * 1000); // 队列程度
        threadPoolExecutor.setThreadPriority(Thread.MAX_PRIORITY);
        threadPoolExecutor.setDaemon(false);
        threadPoolExecutor.setKeepAliveSeconds(300);// 线程空闲时间
        threadPoolExecutor.setThreadNamePrefix("test-Executor-"); // 线程名字前缀
        return threadPoolExecutor;
    }

    /**
     *  异步任务中异常处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandler() {
            @Override
            public void handleUncaughtException(Throwable arg0, Method arg1, Object... arg2) {
                log.error("=========================="+arg0.getMessage()+"=======================", arg0);
                log.error("exception method:"+arg1.getName());
            }
        };
    }
}

  当使用以上的方式时,可在使用 @Async 注解时,不用显示生命线程池的方式就可以使用自定义的线程池。

3.如何设置核心线程数

  对于ThreadPoolTaskExecutorcorePoolSize,一般来说可以根据任务的性质、数量、执行时间等因素进行灵活调整,具体的配置需要根据实际情况来决定。这里提供一些核心线程数设置的建议:

  1. 根据任务的性质来设置corePoolSize

  如果任务量较少且每个任务都非常耗时,可以适当减少核心线程数以节省资源,例如将corePoolSize设置为2-3;如果有大量的耗时短的任务,可以适当增加核心线程数,例如将corePoolSize设置为10-20等。

  1. 根据CPU核心数来设置corePoolSize

  通常情况下,corePoolSize建议设置为CPU核心数的2倍,这样可以保证资源的最大利用。但需要注意的是,当任务的处理时间较长时(例如IO操作),可以适当增加corePoolSize以避免线程空闲等待。

    学习ThreadPoolExecutor 更多可以参考这篇文章:Java线程池实现原理及其在美团业务中的实践

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值