@Async是什么
Spring自带了支持任务调度和异步方法调用的注解,在需要被调用的方法上加上@Async注解,则该方法会被异步调用
@Async使用
ssm项目中使用@Async,创建一个配置类,在配置类上面加@EnableAsync注解;在对应的方法上加@Async注解
@Configuration
@EnableAsync
public class FundConfig implements AsyncConfigurer {
//创建线程池用于执行异步任务
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(512);
executor.setQueueCapacity(8);
executor.setThreadNamePrefix("FundExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy()); //新增拒绝策略
return executor;
}
@Override
public Executor getAsyncExecutor() {
return taskExecutor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
@Component
public class FundsAsyncImpl {
@Async
public Future<String> dealFundsMsg(Map<String, Object> reqMap, String transId){
//dosomething
}
}
图一中自定义线程池,若不自定义则会使用默认线程池,默认线程池有导致内存溢出的风险,因为@Async使用的线程池Bean名称为applicationTaskExecutor,显而易见这个队列设置为Integer.MAX_VALUE,所以会导致堆内存溢出
Spring会先去找类型为TaskExecutor的bean,或者bean名称为“taskExecutor”的bean,如果都没有找到,则使用SimpleAsyncTaskExecutor作为默认线程池
规划线程池大小
简单的但不知是否可行的方法(N为CPU总核数):
如果是CPU密集型应用,则线程池大小设置为N+1
如果是IO密集型应用,则线程池大小设置为2N+1
服务器性能IO优化 中发现一个估算公式:
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目 |
比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
可以得出一个结论:
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
摘自:https://blog.csdn.net/wang20010104/article/details/127337665