线程池使用不规范导致线程数大以及@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")
相关推荐
半瓶榴莲奶^_^1 小时前
jvm java虚拟机
java·jvm
invicinble7 小时前
这里对java的知识体系做一个全域的介绍
java·开发语言·python
wbs_scy7 小时前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·开发语言
ss2737 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
try2find8 小时前
打印ascii码报错问题
java·linux·前端
014-code8 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
Nicander8 小时前
多数据源下@transcation事务踩坑
java·后端
それども9 小时前
DELETE 和 TRUNCATE TABLE区别
java·数据库·mysql
sjsjsbbsbsn9 小时前
大模型核心知识总结
java·人工智能·后端