- 目录
- 背景
- 排查过程
- 解决方案
- 附录
修改jvm参数(新生代与老年代比例)时,看到一台机器java进程的CPU占比时刻保持在300%,觉得不太正常,因此学习排查。
排查过程在线上六台机器中选择一台机器进行排查,top如下:
发现进程178的cpu占用率在304.3%,查看其具体占用高的线程 top -Hp pid:
发现线程pid为806(326),766(2fe),826(33a)的线程占用资源较高,用jstack追踪一下 jstack pid | grep 线程pid16进制,得到如下结果:
在代码中找到对应的方法,查看了逻辑,发现有sleep操作,对阻塞队列取数据的方法为poll:
对poll进行了研究,发现poll是不阻塞的,即poll数据时,取不到则返回null,不会发生中断,不断地轮询会导致把cpu打满。
阻塞方法:
- poll() → poll(long timeout, TimeUnit unit)
如果取不到数据时,则等待一定时间,超时还没取到则返回null。 - poll() → take()
空队列时,则阻塞,线程挂起。
为避免使用take()抛出陈旧连接异常(代码逻辑中有需要token的地方,一段时间更新一次),因此选用方案1以免在不确定的时刻阻塞线程。
使用此方法后,稳定一段时间top,java进程的cpu利用率可基本维持在100左右:
oracle中BlockQueue的poll和take方法解释如下传送门:



