线程池使用不规范导致线程数大以及@Async的规范使用

文章详细内容来自:线程数突增!领导:谁再这么写就滚蛋!

下面是看完后文章的,一个总结

线程池的使用不规范,导致程序中线程数不下降,线程数量大。

临时变量的接口,通过下面简单的线程池执行,

java 复制代码
private static void threadDontGcDemo(){
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.submit(() -> {
            System.out.println("111");
        });
    }

线程不被GC回收,主要是线程池的gc root还是有可达路径的。这里讲个冷知识,这里的线程池的gc root是线程,具体的gc路径是thread->workers->线程池

如果临时采用线程池,需要 手动设置线程池的shutdown,下面写法:

java 复制代码
private static void threadDontGcDemo(){
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.submit(() -> {
            System.out.println("111");
        });
        executorService.shutdown();
    }

原理是,shutdown方法是遍历所有线程,并且调用线程的interrupt()方法,通知线程中断,当worker进行getTask()时,让处于wait的线程打断,抛出异常,workers捕获该worker,workers.remove(w),然后将worker移除workers,这样gc root就不可达了,便会被GC掉。

也就是说线程池的shutdownnow方法调用interruptIdleWorkers去对线程对象interrupt是为了让处于waiting或者是time_waiting的线程抛出异常。

总结为:

  • 线程池调用shutdownnow方法是为了调用worker对象的interrupt方法,来打断那些沉睡中的线程(waiting或者time_waiting状态),使其抛出异常

  • 线程池会把抛出异常的worker对象从workers集合中移除引用,此时被移除的worker对象因为没有到达gc root的路径已经可以被gc掉了

  • 等到workers对象空了,并且当前tomcat线程也结束,此时线程池对象也可以被gc掉,整个线程池对象成功释放

@Async 线程控制

如果不进行线程控制,则异步执行程序越多,会导致线程用尽。

一种方式是全局配置,所有的异步线程共用线程池

java 复制代码
@Configuration
public class AsyncConfig implements AsyncConfigurer {

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(100);
    return executor;
  }

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

    @Override
    public Integer getAsyncExecutor() {
      return 30; // 单位为秒
    }

}

另外一种是,@Async标签指定使用的线程池名称

java 复制代码
@Configuration
@EnableAsync
public class TaskExcutorConfig {
    @Bean("taskExecutor")
    public Executor taskExecutro() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(30);
        taskExecutor.setMaxPoolSize(50);
        taskExecutor.setQueueCapacity(200);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("taskExecutor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        return taskExecutor;
    }

    @Bean("commonExecutor")
    public Executor commonTaskExecutro() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(50);
        taskExecutor.setMaxPoolSize(100);
        taskExecutor.setQueueCapacity(2000);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("commonExecutor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        return taskExecutor;
    }

    @Bean("notificationExecutor")
    public Executor notificationExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(30);
        taskExecutor.setMaxPoolSize(60);
        taskExecutor.setQueueCapacity(2000);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("notificationExecutor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.setAwaitTerminationSeconds(60);
        return taskExecutor;
    }
}

使用时标明:

复制代码
@Async("commonExecutor")
相关推荐
香蕉大香蕉(06敬畏市场)4 分钟前
MySQL 单点详解(08)
java·数据库·mysql·面试·八股
thefool1122668 分钟前
HTTPS协议
java
acd1200916 分钟前
Nginx 反向代理的缓冲区坑:后端响应大时接口偶发 502
java·运维·nginx
装不满的克莱因瓶18 分钟前
支付订单成功异步MQ权益发放设计和开发
java·架构·系统架构·rabbitmq·硬件架构
高冷小鱼殿下37 分钟前
内部类Lambda与枚举
java·开发语言
小蒜学长1 小时前
编程语言在线学习平台的设计与实现(代码+数据库+LW)
java·spring boot·后端·编程语言在线学习平台·在线编码
步行cgn2 小时前
Spring MVC 执行流程详解:一次请求的完整旅程
java·spring·mvc
增量星球2 小时前
Spring AI 2.0 Tool Calling 到底怎么跑起来的:从 @Tool 到两次模型调用
java·agent·springai·ai coding
步行cgn2 小时前
Spring MVC 九大核心角色详解:请求处理链路中的每一个关键组件
java·spring·mvc
智恒百亿2 小时前
一台 5090 八卡服务器怎么分给一个团队用?多模型多任务的显存分配实战
java·大数据·人工智能