当前位置: 首页 > 科技观察

如何定位占用CPU最多的线程

时间:2023-03-16 19:34:33 科技观察

之前有朋友反映帖子的内容应该是有渐变的,逐渐加深。jvm源码分析的文章我发过几篇。可能我自认为已经把内容写的通俗易懂了,但是对于一些接触不多的同学来说还是很难理解。以后我会慢慢改进这个。我今天会发一篇轻松的文章。也许你在工作的过程中也会遇到类似的问题。或许有经验的同学看到这个题目就知道了。想说的,也有自己的定位方法。话不多说,先看代码}catch(Exceptione){}}}.start();}Threadt=newThread(){publicvoidrun(){inti=0;while(true){i=(i++)/100;}}};t.setName("BusiestThread");t.start();}}本例中新建了11个线程,其中10个什么都不做,主要是休眠,另外一个线程一直循环运行。你可以想象这个线程是这个进程中最耗cpu的线程,那么怎么捕捉这个线程呢?首先,我们可以使用top-Hp查看本进程所有线程的CPU消耗情况,得到类似如下的数据$top-Hp18207top-19:11:43up573days,2:43,2users,loadaverage:3.03,3.03,3.02Tasks:44total,1running,43sleeping,0stopped,0zombieCpu(s):18.8%us,0.0%sy,0.0%ni,81.1%id,0.0%wa,0.0%hi,0.0%si,0.0%stMem:99191752ktotal,98683576kused,508176kfree,128248kbuffersSwap:1999864ktotal,191064kused,1808800kfree,17413760kcachedPIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND18250admin20026.1g28m10mR99.90.00:19.50javaTest18207admin20026.1g28m10mS0.00.00:00.00javaTest18208admin20026.1g28m10mS0.00.00:00.09javaTest18209admin20026.1g28m10mS0.00.00:00.00javaTest18210admin20026.1g28m10mS0.00.00:00.00javaTest18211admin20026.1g28m10mS0.00.00:00.00javaTest18212admin20026.1g28m10mS0.00.00:00.00javaTest18213admin20026.1g28m10mS0.00.00:00.00javaTest18214admin20026.1g28m10mS0.00.00:00.00javaTest18215admin20026.1g28m10mS0.00.00:00.00javaTest18216admin20026.1g28m10mS0.00.00:00.00javaTest18217admin20026.1g28m10mS0.00.00:00.00javaTest18218admin20026.1g28m10mS0.00.00:00.00javaTest18219admin20026.1g28m10mS0.00.00:00.00javaTest18220admin20026.1g28m10mS0.00.00:00.00javaTest18221admin20026.1g28m10mS0.00.00:00.00javaTest18222admin20026.1g28m10mS0.00.00:00.00javaTest18223admin20026.1g28m10mS0.00.00:00.00javaTest18224admin20026.1g28m10mS0.00.00:00.00javaTest18225admin20026.1g28m10mS0.00.00:00.00javaTest18226admin20026.1g28m10mS0.00.00:00.00javaTest18227admin20026.1g28m10mS0.00.00:00.00javaTest得到这个结果我们可以看到CPU***的线程就是pid为18250的线程,占99.8%:PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND18250admin20026.1g28m10mR99.90.019.javaT接着我们可以通过jstack的输出来看各个线程栈:$jstack182072016-03-3019:12:23FullthreaddumpOpenJDK64-BitServerVM(25.66-b60mixedmode):"AttachListener"#30daemonprio=9os_prio=0tid=0x00007fb90be13000nid=0x47d7waitingoncondition[0x0000000000000000]java.lang.Thread.State:RUNNABLE"DestroyJavaVM"#29prio=5os_prio=0tid=0x00007fb96245b800nid=0x4720waitingoncondition[0x0000000000000000]java.lang.Thread.State:RUNNABLE"BusiestThread"#28prio=5os_prio=0tid=0x00007fb91498d000nid=0x474arunnable[0x00007fb9065fe000]java.lang.Thread.State:RUNNABLEatTest$2.run(Test.java:18)"Thread-9"#27prio=5os_prio=0tid=0x00007fb91498c800nid=0x4749waitingoncondition[0x00007fb906bfe000]java.lang.Thread.State:TIMED_WAITING)javaating(.lang.Thread.sleep(NativeMethod)atTest$1.run(Test.java:9)"Thread-8"#26prio=5os_prio=0tid=0x00007fb91498b800nid=0x4748waitingoncondition[0x00007fb906ffe000]java.lang.Thread.State:TIMED_WAITING(睡眠)atjava.lang.Thread.sleep(NativeMethod.run)atTest(Test.java:9)"Thread-7"#25prio=5os_prio=0tid=0x00007fb91498b000nid=0x4747waitingoncondition[0x00007fb9073fe000]java.lang.Thread.State:TIMED_WAITING(睡眠)atjava.lang.Thread.sleep(Native$1Method.)atTest运行(Test.java:9)“Thread-6”#24prio=5os_prio=0tid=0x00007fb91498a000nid=0x4746waitingoncondition[0x00007fb9077fe000]java.lang.Thread.State:TIMED_WAITING(睡眠)atjava.lang.Thread.sleep(Native$1Method)at.run(Test.java:9)...在上面的线程栈中,我们注意到nid的值其实就是线程ID,是16进制的。我们把消耗cpu***的线程18250换算成十六进制为0X47A,然后从上面的线程栈中找到nid=0X47A的线程。堆栈为:"BusiestThread"#28prio=5os_prio=0tid=0x00007fb91498d000nid=0x474arunnable[0x00007fb9065fe000]java.lang.Thread.State:RUNNABLEatTest$2.run(Test.java:18)消耗cpu最多的线程即将被发现,是BusinestThread【本文专栏作者李嘉鹏原创文章请微信联系作者公众号(你个假笨,id:lovestblog)获取授权】点此查看作者更多好文