当前位置: 首页 > news >正文

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

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

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

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

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

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

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

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

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 线程控制

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

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

@Configuration
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);return executor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new CustomAsyncExceptionHandler();}@Overridepublic Integer getAsyncExecutor() {return 30; // 单位为秒}}

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

@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")
http://www.lryc.cn/news/146901.html

相关文章:

  • 启莱OA treelist.aspx SQL注入
  • ES是一个分布式全文检索框架,隐藏了复杂的处理机制,核心数据分片机制、集群发现、分片负载均衡请求路由
  • xml和json互转工具类
  • Windows系统下MMDeploy预编译包的使用
  • yolov5自定义模型训练二
  • Spring框架获取用户真实IP(注解式)
  • 利用 IDEA IDE 的轻量编辑模式快速查看和编辑工程外的文本文件
  • MyBatisx代码生成
  • 【日记】文章更新计划
  • UML用例图三种关系(重点)-架构真题(十七)
  • 分层解耦介绍
  • Nginx百科之gzip压缩、黑白名单、防盗链、零拷贝、跨域、双机热备
  • git通过fork-merge request实现多人协同
  • 元素居中的方法总结
  • 后端面试话术集锦第一篇:spring面试话术
  • elasticsearch8.9.1集群搭建
  • 前端调用电脑摄像头
  • 网络编程day1——进程间通信-socket套接字
  • Android-关于页面卡顿的排查工具与监测方案
  • VueX 与Pinia 一篇搞懂
  • 指针与空间按钮的交互
  • java八股文面试[数据库]——慢查询优化
  • 《Flink学习笔记》——第十章 容错机制
  • 【LeetCode-中等题】230. 二叉搜索树中第K小的元素
  • DQL语句的用法(MySQL)
  • 【Navicat Premium 16】使用Navicat将excel的数据进行单表的导入,详细操作
  • 学习笔记230810--vue项目中get请求的两种传参方式
  • 分享一种针对uni-app相对通用的抓包方案
  • 【2023百度之星备赛】码蹄集 BD202301 公园(BFS求最短路)
  • 2022年下半年系统架构设计师真题(下午带答案)