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。