1.場景一: HashMap併發導致死循環
public class Test {
public static class HashMapThread extends Thread {
private static AtomicInteger ai = new AtomicInteger(0);
private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(1);
public void run() {
while (ai.get() < 100000) {
map.put(ai.get(), ai.get());
ai.incrementAndGet();
System.err.println(Thread.currentThread().getName() + "put>>" + ai.get());
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
HashMapThread hmt0 = new HashMapThread();
HashMapThread hmt1 = new HashMapThread();
HashMapThread hmt2 = new HashMapThread();
HashMapThread hmt3 = new HashMapThread();
HashMapThread hmt4 = new HashMapThread();
hmt0.start();
hmt1.start();
hmt2.start();
hmt3.start();
hmt4.start();
}
}
}
反覆運行上面程序,直到你試出了死循環就ok了。
我們用jps查看進程id,然後用jstack 進程ID 查看堆棧情況:
上面可以定位到你的業務代碼。
2.場景二: 分析死鎖
public class Test {
static Lock lock1 = new ReentrantLock();
static Lock lock2 = new ReentrantLock();
public static void main(String[] args) {
Thread t1 = new Thread() {
@Override
public void run() {
try {
lock1.lock();
TimeUnit.SECONDS.sleep(1);
lock2.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
try {
lock2.lock();
TimeUnit.SECONDS.sleep(1);
lock1.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.setName("mythread1");
t2.setName("mythread2");
t1.start();
t2.start();
}
}
jstack pid 查看關鍵信息
3.場景三: 線上定位
當我們到線上時,會有無數個線程在運行,就不能用簡單的jstack pid 來查看定位了
上面會有很多很多,無法定位出佔cpu高的線程。
下面介紹具體定位步驟:
1.top找出cpu佔用高的進程pid
2.根據pid查出線程
top -Hp 153527
2.打印線程id的十六進制
[root@TXIDC-lyadmin-1-AB ~]# printf "%x\n" 153586
257f2
2.打印線程id的十六進制
jstack 進程id | grep 線程id的十六進制
對線程狀態進行分析。線程狀態如下所示:
1) 死鎖,Deadlock(重點關注)
2) 執行中,Runnable
3) 等待資源,Waiting on condition(重點關注,等待什麼資源)
4) 等待獲取監視器,Waiting on monitor entry(重點關注)
5) 暫停,Suspended
6) 對象等待中,Object.wait() 或 TIMED_WAITING
7) 阻塞,Blocked(重點關注)
8) 停止,Parked