1、首先使用jps -v命名获取java进程id
jps -mlv
2、使用jstack命令导出线程堆栈dump文件
Jstack -l pid >>/data/logs/test.dump
3、查询进程id的所有线程命令:
ps -T -p pid
查询看耗时最长或者最好cpu的线程id,转换为16进制,到dump文件中查找线程堆栈信息
4、线程堆栈信息分析
观看线程锁的技巧:
1)当一个线程占有一个锁的时候,堆栈上会打印一个:-locked<0x22bffb60>
2)当一个线程等待其他线程释放该锁,线程堆栈会打印一个:-waiting tolock<0x22bffb60>
3)当一个线程占有一个锁,但又执行在该锁的wait上,线程堆栈中首先打印locked,然后打印-waiting on<0x22c03c60>
5、线程状态
1)RUNNABLE
处于RUNNABLE状态的线程不一定会消耗CPU,比如socket io,线程真正从网络上读取数据,但实际上网络的io线程大部分是挂起的,只有当数据到达后,线程才会被唤起(挂起发生在本地native中),在本地代码中的挂起,虚拟机无法知道真正的状态:
2)TIMED_WAITING(on object monitor)表示当前线程挂起一段时间,说明该线程正在执行obj.wait()方法,该线程不消耗cpu;
3)TIMED_WAITING(sleeping)表示当前线程挂起一段时间,该线程正在执行Thread.sleep()方法,如:
4)WAITING(on object monitor)表示当前线程正在被挂起,正在执行无参数的obj.wait()方法,只能通过notify()方法唤醒,因此不消耗cpu,如:
总结:
- 处于timed_waiting,waiting状态的线程一定不消耗cpu,处于runnable状态的线程不一定会消耗cpu,要结合当前线程代码的性质判断,是否消耗cpu
- 如果是纯java运算代码,则消耗cpu
- 如果网络io,很少消耗cpu
- 如果是本地代码,集合本地代码的性质,可以通过pstack获取本地的线程堆栈,如果是纯运算代码,则消耗cpu,如果被挂起,则不消耗,如果是io,则不怎么消耗cpu。