題目描述 :http://fresh.qunar.com/pages/viewpage.action?pageId=5570576
jvm提供了一個jstack的工具,能夠把該jvm中運行的線程堆棧導出,具體見j.stack文件
好比
"DubboServerHandler-192.168.6.96:20880-thread-143" daemon prio=10 tid=0x00007f3d8006d000 nid=0x1807 waiting on condition [0x00007f3d67cfa000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00007f3f7c16b630> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:422)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:857)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
DubboServerHandler-192.168.6.96:20880-thread-143爲線程的名字,tid爲線程id ,java.lang.Thread.State: WAITING,WAITING爲線程狀態
waiting on condition [0x00007f3d67cfa000]表示該線程waiting在tid=0x00007f3d67cfa000的線程上
請寫一個程序,解析出線程名,線程id,線程狀態,以及哪些線程wait在同一個condition上 。就是說匹配「waiting on condition」的線程進行統計。
輸出結果按照等待同一個condition的線程數從大到小排序。
輸出格式以下:
condition id,count:
線程id|線程名|線程狀態
線程id|線程名|線程狀態
線程id|線程名|線程狀態
condition id,count:
線程id|線程名|線程狀態
線程id|線程名|線程狀態
……
GuaExam2.java
package libinchen;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class GuaExam2 {
public static Map<String, Integer> m1 = Maps.newHashMap(); // String 中存儲的是 condition_id
public static Map<String, List<StringBuffer>> m2 = Maps.newHashMap();
// StringBuffer 中存儲的是字符串 "線程 id | 線程名 | 線程狀態"
private static void getRightLine(File f1) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(f1));
String strE1 = "waiting on condition ["; // 匹配
String str;
while ((str = br.readLine()) != null) {
int ks = str.indexOf(strE1); // 找到符合條件的行
if (ks != -1) { // 表明找到 E1 的位置
getTwoMap(str, br.readLine(), ks, strE1.length());
}
}
}
public static void p(Object o) {
System.out.println(o);
}
public static void getTwoMap(String first, String second, int begin, int sLen) { // 分析符合條件的行,提取出來
String seTid = "tid=", sNameEnd = "\" ";
String E2 = "java.lang.Thread.State: ";
String conTid, sTid, sName, sState;
conTid = first.substring(begin + sLen, begin + sLen + 18); // 提取構造 condition,tid
if (!m1.containsKey(conTid)) {
m1.put(conTid, 1);
} else {
int freq = m1.get(conTid);
m1.put(conTid, freq + 1);
} // 構造 Map m1
int ks = first.indexOf(seTid);
sTid = first.substring(ks + seTid.length(), ks + seTid.length()+ 18); // 構造 tid
ks = first.indexOf(sNameEnd);
sName = first.substring(1, ks); // 構造 線程名 : sName
StringBuffer son = new StringBuffer();
son.append(sTid).append("|").append(sName).append("|");
ks = second.indexOf(E2);
if (ks != -1) {
String tmp = second.substring(ks + E2.length());
for (int i = 0; i < tmp.length(); i++) {
if (tmp.charAt(i) == ' ') {
break;
}
son.append(tmp.charAt(i));
}
}
if (!m2.containsKey(conTid)) {
List<StringBuffer> kl = Lists.newArrayList();
kl.add(son);
m2.put(conTid, kl);
} else {
List<StringBuffer> kl = m2.get(conTid);
kl.add(son);
m2.put(conTid, kl);
}
}
public static Map sortByValue(Map<String, Integer> map) {
List list = new LinkedList(map.entrySet());
Collections.sort(list, new Comparator() {
public int compare(Object o1, Object o2) {
return ((Comparable) ((Map.Entry) o2).getValue())
.compareTo(((Map.Entry) o1).getValue());
}
});
Map result = Maps.newLinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
result.put(entry.getKey(), entry.getValue());
}
return result;
}
static int lineCount = 0;
/* Main */
public static void startMain() throws IOException {
getRightLine(new File("/home/mxw/j.stack"));
//p(GuaExam2.class.getClass().getResource("/j.stack").getPath());
//p(GuaExam2.class.getClass().getResource("/").getPath());
//File file = new File(GuaExam2.class.getClass().getResource("/").getPath() + "result.txt");
File file = new File("/home/mxw/examresult/libinchen.txt");
PrintStream out = new PrintStream(new FileOutputStream(file));
System.setOut(out);
m1 = sortByValue(m1);
for (String key : m1.keySet()) {
p("conditionid:" + key + ",count:" + m2.get(key).size());
lineCount++;
Iterator it = m2.get(key).iterator();
while (it.hasNext()) {
p(it.next());
lineCount++;
}
}
//p(lineCount);
}
}
Exam.java
package libinchen;
import java.io.File;
import java.io.IOException;
public class Exam {
public static void exam() {
GuaExam2 analyse = new GuaExam2();
try {
analyse.startMain();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
public static void main(String[] args) throws IOException {
Exam.exam();
}
*/
}
pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qunar.fresh</groupId>
<artifactId>Exam1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Exam1</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
</dependencies>
</project>