已删除用户
发布于 2023-08-16 / 0 阅读 / 0 评论 / 0 点赞

@Async异步执行

springboot-@Async默认线程池导致OOM问题

内存溢出的三种类型:

1.第一种OutOfMemoryError: PermGen space,发生这种问题的原意是程序中使用了大量的jar或class

2.第二种OutOfMemoryError: Java heap space,发生这种问题的原因是java虚拟机创建的对象太多

3.第三种OutOfMemoryError:unable to create new native thread,创建线程数量太多,占用内存过大

@Async注解

@async注解的方法不能跟调用者的方法在一个类里面.不然会造成不生效.可以理解为一个类就是一个线程池,调用者的方法就是一个线程,这里需要单独开一个线程去调用

自定义线程池

    @Bean
    public Executor taskThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix(threadNamePrefix);
        executor.setAwaitTerminationSeconds(awaitTerminationSeconds);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }

@Async默认使用Bean Name为executor的线程池。也可以根据Bean Name指定特定线程池

  @Async("taskThreadPool")
  public void asyncMethod() {
   
  }

SimpleAsyncTaskExecutor

Async注解默认使用的是 SimpleAsyncTaskExecutor 该线程池默认来一个任务创建一个线程

在压测的情况下,该线程池默认来一个任务创建一个线程,这时就会不断创建大量线程,

SimpleAsyncTaskExecutor提供了限流机制

通过concurrencyLimit属性来控制开关,当concurrencyLimit>=0时开启限流机制,默认

关闭限流机制即concurrencyLimit=-1,当关闭情况下,会不断创建新的线程来处理任务

首先任务进来,会循环判断当前执行线程数是否超过concurrencyLimit,如果超了,则当前线程调用wait方法,释放monitor对象锁,进入等待

线程任务执行完毕后,当前执行线程数会减一,会调用monitor对象的notify方法,唤醒等待状态下的线程,等待状态下的线程会竞争monitor锁,竞争到,会继续执行线程任务

@Configuration
@EnableAsync
public class AsyncCommonConfig extends AsyncConfigurerSupport {
    @Override
    public Executor getAsyncExecutor() {
        SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
        //设置允许同时执行的线程数为10
 executor.setConcurrencyLimit(10);
        return executor;
    }
}


1.开启限流情况下,能有效控制应用线程数
2.虽然可以有效控制线程数,但执行效率会降低,会出现主线程等待,线程竞争的情况。
3.限流机制适用于任务处理比较快的场景,对于应用处理时间比较慢的场景并不适用。


评论