【BUG记录】线程池满

现象

现场开发人员反映线程池满,他们把线程池大小配为5000后,还是不够。

程序业务大概是监听设备是否有状态变化,如果变化则启动一个线程去处理设备的业务。现场设备数大概300个左右,并发量不大,所以正常处理不需要这么多线程。

解决过程

Step1.抓取线程DUMP日志

很明显的是不应该需要这么多线程,那么应该是线程出了问题,所以先抓线程的dump日志。

有4802个处理业务的线程在等待readBase方法的ReentrantLock。统计了一下每个lock大约有20-30个线程在等待,则5000/25≈200,这个数字和设备数差不多。
说明程序目前实际上是在处理大约200个设备的业务,但是A设备的第一个业务还没处理完,而第2-25个业务就已经过来了。
但程序逻辑设计上不能并发处理设备的业务,所以一个设备一个lock,所以第2-25个请求都阻塞在lock这了。

Step2.继续找lock的源头

Step3.猜想

目前总结看到的现象:

  1. 没有死锁
  2. 业务代码的线程被阻塞在log appender的doAppen方法上,这个方法被synchronized修饰了

所以猜想,线程堆积不是由死锁引起的,而是log appender的doAppend方法处理太慢,导致的堆积。

然后又随机打了两个时间点的线程dump,发现每个dump日志中执行WinNTFileSystem.getLength的线程都不同,验证了上述猜想。

解决办法

将log的appender换成异步的appender,经过验证问题解决。

posted @ 2023-03-30 19:17  daheww  阅读(89)  评论(0编辑  收藏  举报