项目出现大量ThreadPoolExecutor线程的问题

线上只要运行一段时间就会出现接口访问缓慢甚至假死的情况,用arthas查看线程数显示有一万多个线程在等待.查看线程dump全都是ThreadPoolExecutor线程池的线程.可是项目里没有显式使用的地方,希望可以给一个排查思路

img

img

你的这个问题可能是由于线程池的参数设置不合理或者使用了无界队列导致的。你可以尝试以下几个排查思路:

  • 检查你的项目中是否使用了Executors类的newFixedThreadPool或newCachedThreadPool方法来创建线程池,这些方法可能会导致OOM或者任务堆积。建议使用ThreadPoolExecutor的构造函数来创建线程池,并根据业务场景来设置corePoolSize、maximumPoolSize、workQueue等参数。

  • 注意检查项目中是否使用了局部线程池,即在方法内部创建线程池并执行任务。这样可能会造成系统资源耗尽,因为任务执行完后没有执行shutdown()方法或有其他不当引用。可以将线程池定义为全局变量或者单例模式,并在合适的时机调用shutdown()方法。

  • 还有就是检查项目中是否给线程池指定了有意义的名称,方便出错时回溯。可以使用ThreadFactoryBuilder来构造ThreadFactory,并给不同类别的业务用不同的线程池。

  • 看看你是否使用了无界队列,如LinkedBlockingQueue,如果使用来作为线程池的工作队列。这样可能会导致大量新任务在队列中堆积,最终导致OOM。建议你使用有界队列,如ArrayBlockingQueue或PriorityBlockingQueue,并根据任务类型和数量来合理设置队列大小。

  • 检查项目中是否合理设置了线程池的核心线程数和最大线程数。这两个参数需要根据CPU核心数、CPU目标利用率、任务类型、任务等待时间和计算时间等因素来计算。一般来说,对于CPU密集型任务,核心线程数等于CPU核心数;对于IO密集型任务,核心线程数等于CPU核心数乘以一个系数(通常为2)。

针对线程池导致的接口访问缓慢甚至假死的情况,您可以尝试以下的排查思路:

1.通过 jps 命令找出应用进程ID,然后使用 jstack [进程ID] > thread_dump.log 命令生成线程 dump 日志,再通过分析线程 dump 日志来确定具体问题。

2.通过代码审查,检查是否在开发过程中调用了 Executors.newFixedThreadPool() 或者其他 ThreadPoolExecutor 相关的代码。

3.检查代码中是否有循环任务不当地使用线程池执行方式,导致任务提交过多,最终耗尽线程资源。

4.排查是否存在线程泄漏的问题,即程序在执行完任务后未能及时将线程资源回收。

5.检查线程池参数设置是否合理,例如核心线程数、最大线程数、队列容量等参数合理性。

6.使用工具检查线程池的运行状态,例如使用 Java VisualVM 判断线程池当前的状态是否正常。

已经找到问题,代码里有个地方每次查询都创建ThreadPoolExecutor对象又没注销