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


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

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

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

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

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

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

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

    1. private static void threadDontGcDemo(){
    2.         ExecutorService executorService = Executors.newFixedThreadPool(10);
    3.         executorService.submit(() -> {
    4.             System.out.println("111");
    5.         });
    6. executorService.shutdown();
    7.     }

    原理是,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 线程控制

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

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

    1. @Configuration
    2. public class AsyncConfig implements AsyncConfigurer {
    3. @Override
    4. public Executor getAsyncExecutor() {
    5. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    6. executor.setCorePoolSize(10);
    7. executor.setMaxPoolSize(20);
    8. executor.setQueueCapacity(100);
    9. return executor;
    10. }
    11. @Override
    12. public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    13. return new CustomAsyncExceptionHandler();
    14. }
    15. @Override
    16. public Integer getAsyncExecutor() {
    17. return 30; // 单位为秒
    18. }
    19. }

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

    1. @Configuration
    2. @EnableAsync
    3. public class TaskExcutorConfig {
    4. @Bean("taskExecutor")
    5. public Executor taskExecutro() {
    6. ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    7. taskExecutor.setCorePoolSize(30);
    8. taskExecutor.setMaxPoolSize(50);
    9. taskExecutor.setQueueCapacity(200);
    10. taskExecutor.setKeepAliveSeconds(60);
    11. taskExecutor.setThreadNamePrefix("taskExecutor--");
    12. taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    13. taskExecutor.setAwaitTerminationSeconds(60);
    14. return taskExecutor;
    15. }
    16. @Bean("commonExecutor")
    17. public Executor commonTaskExecutro() {
    18. ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    19. taskExecutor.setCorePoolSize(50);
    20. taskExecutor.setMaxPoolSize(100);
    21. taskExecutor.setQueueCapacity(2000);
    22. taskExecutor.setKeepAliveSeconds(60);
    23. taskExecutor.setThreadNamePrefix("commonExecutor--");
    24. taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    25. taskExecutor.setAwaitTerminationSeconds(60);
    26. return taskExecutor;
    27. }
    28. @Bean("notificationExecutor")
    29. public Executor notificationExecutor() {
    30. ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    31. taskExecutor.setCorePoolSize(30);
    32. taskExecutor.setMaxPoolSize(60);
    33. taskExecutor.setQueueCapacity(2000);
    34. taskExecutor.setKeepAliveSeconds(60);
    35. taskExecutor.setThreadNamePrefix("notificationExecutor--");
    36. taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
    37. taskExecutor.setAwaitTerminationSeconds(60);
    38. return taskExecutor;
    39. }
    40. }

    使用时标明:

    @Async("commonExecutor")
  • 相关阅读:
    JDK21新特性
    3 内存访问
    S7-200SMART PLC实现冒泡排序的具体方法和程序示例
    QT笔记——vs中的qt项目 可调试源码
    【java_wxid项目】【第九章】【Apache Mybatis集成】
    解决-linux 一次 高并发处理过程。
    大数据精准营销一站式解决你的获客难题
    给大家分享一份适合练手的软件测试实战项目
    2022年金九银十,秋招Java后端开发最全面试攻略,卷对方向,才拿得到心仪的大厂offer
    从猿六年---C++笔试\面试的不成熟小建议来啦
  • 原文地址:https://blog.csdn.net/seapeak007/article/details/132562904