示例代碼:
public class CPULockTest { private static Object lock1 = new Object(); private static Object lock2 = new Object(); public static void main(String[] args) { new Thread(()->{ synchronized (lock1){ try { System.out.println(Thread.currentThread().getName()+"得到lock1"); Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2){ System.out.println(Thread.currentThread().getName()+"得到lock2"); } } },"線程1").start(); new Thread(()->{ synchronized (lock2){ try { System.out.println(Thread.currentThread().getName()+"得到lock2"); Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1){ System.out.println(Thread.currentThread().getName()+"得到lock1"); } } },"線程2").start(); } }
找出pid(進程ID)
top命令
在linux環境下,可以通過top命令查看各個進程的cpu使用情況,默認按cpu使用率排序
jps命令
顯示指定系統內所有的HotSpot虛擬機進程。
通過進程id看線程情況
linux:通過top -Hp 4548可以查看該進程下各個線程的cpu使用情況,有線程的pid;
mac:
jstack查看當前進程的狀態
➜ ~ jstack 4548 2017-03-14 09:57:31 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode): "Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007f8c1a222000 nid=0x350f waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007f8c1a26c800 nid=0x1703 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "線程2" #11 prio=5 os_prio=31 tid=0x00007f8c1a223000 nid=0x5103 waiting for monitor entry [0x000070000134f000] java.lang.Thread.State: BLOCKED (on object monitor) at cn.gov.zcy.fixed.CPULockTest.lambda$main$1(CPULockTest.java:35) - waiting to lock <0x0000000795b08d58> (a java.lang.Object) - locked <0x0000000795b08d68> (a java.lang.Object) at cn.gov.zcy.fixed.CPULockTest$$Lambda$2/859417998.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) "線程1" #10 prio=5 os_prio=31 tid=0x00007f8c19967800 nid=0x4f03 waiting for monitor entry [0x000070000124c000] java.lang.Thread.State: BLOCKED (on object monitor) at cn.gov.zcy.fixed.CPULockTest.lambda$main$0(CPULockTest.java:21) - waiting to lock <0x0000000795b08d68> (a java.lang.Object) - locked <0x0000000795b08d58> (a java.lang.Object) at cn.gov.zcy.fixed.CPULockTest$$Lambda$1/1020391880.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) "Monitor Ctrl-Break" #9 daemon prio=5 os_prio=31 tid=0x00007f8c1a224800 nid=0x4d03 runnable [0x0000700001149000] java.lang.Thread.State: RUNNABLE at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409) at java.net.ServerSocket.implAccept(ServerSocket.java:545) at java.net.ServerSocket.accept(ServerSocket.java:513) at com.intellij.rt.execution.application.AppMain$1.run(AppMain.java:90) at java.lang.Thread.run(Thread.java:745) "Service Thread" #8 daemon prio=9 os_prio=31 tid=0x00007f8c1a029800 nid=0x4903 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007f8c1a83f800 nid=0x4703 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007f8c19845000 nid=0x4503 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007f8c1a800800 nid=0x4303 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007f8c1a028000 nid=0x320f runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007f8c1a82d000 nid=0x3003 in Object.wait() [0x000070000092e000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000795588e98> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x0000000795588e98> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209) "Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007f8c19805000 nid=0x2e03 in Object.wait() [0x000070000082b000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000795586b40> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x0000000795586b40> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "VM Thread" os_prio=31 tid=0x00007f8c1a014000 nid=0x2c03 runnable "GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007f8c1a818800 nid=0x2403 runnable "GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007f8c1a000800 nid=0x2603 runnable "GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007f8c19809000 nid=0x2803 runnable "GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007f8c19809800 nid=0x2a03 runnable "VM Periodic Task Thread" os_prio=31 tid=0x00007f8c1b029800 nid=0x4b03 waiting on condition JNI global references: 324 Found one Java-level deadlock: ============================= "線程2": waiting to lock monitor 0x00007f8c1a0176b8 (object 0x0000000795b08d58, a java.lang.Object), which is held by "線程1" "線程1": waiting to lock monitor 0x00007f8c1a0178c8 (object 0x0000000795b08d68, a java.lang.Object), which is held by "線程2" Java stack information for the threads listed above: =================================================== "線程2": at cn.gov.zcy.fixed.CPULockTest.lambda$main$1(CPULockTest.java:35) - waiting to lock <0x0000000795b08d58> (a java.lang.Object) - locked <0x0000000795b08d68> (a java.lang.Object) at cn.gov.zcy.fixed.CPULockTest$$Lambda$2/859417998.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) "線程1": at cn.gov.zcy.fixed.CPULockTest.lambda$main$0(CPULockTest.java:21) - waiting to lock <0x0000000795b08d68> (a java.lang.Object) - locked <0x0000000795b08d58> (a java.lang.Object) at cn.gov.zcy.fixed.CPULockTest$$Lambda$1/1020391880.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) Found 1 deadlock.
jstack命令生成的thread dump信息包含了JVM中所有存活的線程,為了分析指定線程,必須找出對應線程的調用棧,應該如何找?
在top命令中,已經獲取到了占用cpu資源較高的線程pid,將該pid轉成16進制的值,在thread dump中每個線程都有一個nid,找到對應的nid即可;隔段時間再執行一次stack命令獲取thread dump,區分兩份dump是否有差別。