jstack 分析cpu过高的场景

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章