一些问题分析过程
1. 排查空余线程、线程上下文切换情况
先使用 vmstat 测量上下文切换次数。vmstat 命令详解
# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 16097480 195788 6907592 0 0 0 4 1 1 0 0 99 0 0 0 0 0 16097396 195788 6907592 0 0 0 0 1485 3055 1 1 99 0 0 0 1 0 16097492 195788 6907596 0 0 0 20 1579 3122 0 1 98 1 0 0 0 0 16097524 195788 6907632 0 0 0 0 1524 3094 0 0 99 0 0 0 0 0 16097332 195788 6907632 0 0 0 0 1516 3063 0 1 99 0 0
cs (Content Switch)表示上下文切换的次数。从上面的测试结果来看,上下文每1秒切换3000多次,这表示空闲线程数比较多才会造成上下文切换次数过高的情况。
接下来我们要解决如何减少上下文切换。
1.1 使用 jstack 命令 dump线程信息。
先用 jps 命令,获取到Java应用的pid,用 jstack 命令dump线程信息,看看pid为 502411 的进程里的线程都在做什么?
# jstack 502411 > /home/tmp/dump01
如果当前用户没有权限,可以在命令前加 sudo
1.2 统计所有线程分别处于什么状态,主要看 WAITING(onobjectmonitor)
# grep java.lang.Thread.State dump01 | awk '{print $2$3$4$5}' | sort | uniq -c 46 RUNNABLE 1 TIMED_WAITING(onobjectmonitor) 23 TIMED_WAITING(parking) 7 TIMED_WAITING(sleeping) 212 WAITING(onobjectmonitor) 43 WAITING(parking)
1.3 打开 dump 文件查看出 WAITING(onobjectmonitor) 的线程在做什么?
这些线程的大概率是 Tomcat、Jboss 等框架启动时自创建,这样可以直接调试启动参数。
如果是程序代码中出现空闲线程,需要调整连接池之类的参数了。