欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring4.3.x 使用@Async注解实现异步执行 ThreadPoolExecutor did not accept task: AsyncExecutionInterceptor

程序员文章站 2022-05-22 20:21:30
...

@Async

首先我们需要了解其规则——@Async有两个限制:

  • 必须仅应用在public方法上
  • 自执行——从相同类中调用异步方法不起作用。

原因很简单——public方法能够被代理,自执行不工作是因为它绕过代理并直接调用底层方法。

 

  • 处理调整报
    
    Executor [[email protected][Running, pool size = 200, active threads = 1, queued tasks = 420, completed tasks = 244874312]] did not accept task: [email protected]4f9ae398
  •  
@Configuration
@ComponentScan("com.xxx.xxx.biz.*.*Service")
@EnableAsync
public class ThreadConfig extends AsyncConfigurerSupport{
  
     @Override
     public ThreadPoolTaskExecutor getAsyncExecutor() {
          ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
          // 核心池的大小(即线程池中的线程数目大于这个参数时,提交的任务会被放进任务缓存队列)
          executor.setCorePoolSize(50);
          // 线程池最大能容忍的线程数
          executor.setMaxPoolSize(500);
          // 任务缓存队列,用来存放等待执行的任务
          executor.setQueueCapacity(800);
          executor.setWaitForTasksToCompleteOnShutdown(true);
          // 线程池维护线程所允许的空闲时间
          executor.setAwaitTerminationSeconds(60 * 30);
          executor.setThreadNamePrefix("xxx-xxx-thread-");
          // 线程池对拒绝任务(无线程可用)的处理策略 ThreadPoolExecutor.CallerRunsPolicy策略 ,调用者的线程会执行该任务,如果执行器已关闭,则丢弃.
          executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
          executor.initialize();  
          return executor;  
     }

     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
          return new AsyncUncaughtExceptionHandler() {
               @Override
               public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
                    log.warn("ThreadConfig处理异步常异-->{},{}",method.getName(),objects,throwable);
               }
          };
     }
}
在ThreadPoolExecutor中表现为:

如果当前运行的线程数小于corePoolSize,那么就创建线程来执行任务(执行时需要获取全局锁)。
如果运行的线程大于或等于corePoolSize,那么就把task加入BlockQueue。
如果创建的线程数量大于BlockQueue的最大容量,那么创建新线程来执行该任务。
如果创建线程导致当前运行的线程数超过maximumPoolSize,就根据饱和策略来拒绝该任务。