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