本節将通過減少線上大量WAITING的線程,來減少上下文切換次數。
第一步:用jstack指令dump線程資訊,看看pid為3117的程序裡的線程都在做什麼。
sudo -u admin /opt/ifeve/java/bin/jstack 31177 > /home/tengfei.fangtf/dump17
第二步:統計所有線程分别處于什麼狀态,發現300多個線程處于WAITING(onobject-monitor)狀态。
[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk ‘{print $2$3$4$5}’
| sort | uniq -c
39 RUNNABLE
21 TIMED_WAITING(onobjectmonitor)
6 TIMED_WAITING(parking)
51 TIMED_WAITING(sleeping)
305 WAITING(onobjectmonitor)
3 WAITING(parking)
第三步:打開dump檔案檢視處于WAITING(onobjectmonitor)的線程在做什麼。發現這些線程基本全是JBOSS的工作線程,在await。說明JBOSS線程池裡線程接收到的任務太少,大量線程都閑着。
“http-0.0.0.0-7001-97” daemon prio=10 tid=0x000000004f6a8000 nid=0x555e in
Object.wait() [0x0000000052423000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpointWorker.await(AprEndpoint.java:1464)
-
locked <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpointWorker.run(AprEndpoint.java:1489)
at java.lang.Thread.run(Thread.java:662)
第四步:減少JBOSS的工作線程數,找到JBOSS的線程池配置資訊,将maxThreads降到100。
<maxThreads=“250” maxHttpHeaderSize=“8192”
emptySessionPath=“false” minSpareThreads=“40” maxSpareThreads=“75”
maxPostSize=“512000” protocol=“HTTP/1.1”
enableLookups=“false” redirectPort=“8443” acceptCount=“200” bufferSize=“16384”
connectionTimeout=“15000” disableUploadTimeout=“false” useBodyEncodingForURI= “true”>
第五步:重新開機JBOSS,再dump線程資訊,然後統計WAITING(onobjectmonitor)的線程,發現減少了175個。WAITING的線程少了,系統上下文切換的次數就會少,因為每一次從WAITTING到RUNNABLE都會進行一次上下文的切換。讀者也可以使用vmstat指令測試一下。
[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk ‘{print $2$3$4$5}’
| sort | uniq -c
44 RUNNABLE
22 TIMED_WAITING(onobjectmonitor)
9 TIMED_WAITING(parking)
36 TIMED_WAITING(sleeping)
130 WAITING(onobjectmonitor)