今天在复习多线程的时候写了一个死锁,突然看到网上有人用jstack的命令参数可以查看程序中每个线程的运行情况,于是就尝试着自己动手操作了一下。在cmd下运行jstack -h
看到图中有一个jstack中所有的命令后面都要接上一个pid(进程id,就是我们运行程序的id)。但是这个我不知道啊。于是又去网上找了一些博客看了一下。发现了jvisualvm这个参数,抱着试试看的心里。在dos命令行中输入jvisualvm。输入之后才发现了自己学习java一直错过了一个新天地。
这里面不仅有我们现在运行程序的pid还有我们程序线程的运行状态,还有jvm底层参数的各种信息,而且是图形化界面。
好了,这个东西以后慢慢再研究,可以当成我们学习并发编程的一个监控工具使用。
因为我写了一个死锁程序。我在dos命令行中启动死锁程序:
死锁代码
public class DeadLock extends Thread { public static Object m=new Object(); public static Object n=new Object(); public static void dead() throws InterruptedException { synchronized (m){ Thread.sleep(2000); synchronized (n) { System.out.println(1); } } } public static void d() { synchronized (n) { synchronized (m) { System.out.println(2); } } } public static void main(String[] args){ DeadLock lock=new DeadLock(); Thread t1=new Thread(new Runnable() { @Override public void run() { try { dead(); } catch (InterruptedException e) { e.printStackTrace(); } } });t1.start(); Thread t2=new Thread(new Runnable() { @Override public void run() { d(); } });t2.start(); } }
可以看到完全锁住了。
我们使用jvisualvm代开图形化工具查看死锁程序的pid
其实我们在这里面就可以看到visualvm会给我们报错,发现死锁。Thread-1,Thread-2处于监视状态。我们看到程序的pid为122480.。在dos命令行中输入 jstack -l 122480
如图中所示,线程二想要去获取对象m的监视器锁,而这个锁被线程一所占有,线程一想要去获取对象n的监视器锁,而这个锁被线程二所占有。
除开Thread-1和Thread-2之外,其实jstack罗列了所有的线程。
d:\java>jstack -l 122480
2018-08-21 17:08:19
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.112-b15 mixed mode):
"JMX server connection timeout 19" #19 daemon prio=5 os_prio=0 tid=0x000000001bef4000 nid=0x199ec in Object.wait() [0x000000001c6ff000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
- locked <0x00000000d7a10178> (a [I)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"RMI Scheduler(0)" #18 daemon prio=5 os_prio=0 tid=0x000000001bef3000 nid=0x1b320 waiting on condition [0x000000001c5fe000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d7a00730> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"RMI TCP Connection(1)-192.168.1.104" #17 daemon prio=5 os_prio=0 tid=0x000000001a74d800 nid=0x1def0 runnable [0x000000001bcfe000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00000000d7a18818> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/1821163498.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x00000000d7a6afd0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"RMI TCP Accept-0" #16 daemon prio=5 os_prio=0 tid=0x000000001a692000 nid=0x1dd38 runnable [0x000000001bafe000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x00000000d7a08940> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000003390800 nid=0x1df64 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Thread-2" #13 prio=5 os_prio=0 tid=0x000000001a532000 nid=0x1d78c waiting for monitor entry [0x000000001b2fe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock.d(DeadLock.java:22)
- waiting to lock <0x00000000d7a20300> (a java.lang.Object)
- locked <0x00000000d7a202f0> (a java.lang.Object)
at DeadLock$2.run(DeadLock.java:42)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001a531000 nid=0x1df58 waiting for monitor entry [0x000000001b1ff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at DeadLock.dead(DeadLock.java:11)
- waiting to lock <0x00000000d7a202f0> (a java.lang.Object)
- locked <0x00000000d7a20300> (a java.lang.Object)
at DeadLock$1.run(DeadLock.java:33)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001a4a9800 nid=0x1d1c8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread3" #9 daemon prio=9 os_prio=2 tid=0x000000001a432800 nid=0x1da7c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001a42e800 nid=0x1dd68 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001a420800 nid=0x1d028 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001a41e800 nid=0x1dd70 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001a419800 nid=0x1d638 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001a3c7000 nid=0x1a310 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000018492800 nid=0x1dffc in Object.wait() [0x000000001a88f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000d7a382f8> (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)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000003486000 nid=0x1de38 in Object.wait() [0x000000001a38f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000d7a30a48> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x0000000018488800 nid=0x1dcec runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000033a6800 nid=0x1dda0 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000033a8000 nid=0x1dde8 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000033a9800 nid=0x1cea0 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000033ab000 nid=0x1d338 runnable
"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000000033ad800 nid=0x1aee4 runnable
"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00000000033ae800 nid=0x1da8c runnable
"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00000000033b2000 nid=0x1d2c4 runnable
"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00000000033b3000 nid=0x14a3c runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001a526800 nid=0x1d74c waiting on condition
JNI global references: 242
Found one Java-level deadlock:
=============================
"Thread-2":
waiting to lock monitor 0x0000000018490cb8 (object 0x00000000d7a20300, a java.lang.Object),
which is held by "Thread-1"
"Thread-1":
waiting to lock monitor 0x0000000018492158 (object 0x00000000d7a202f0, a java.lang.Object),
which is held by "Thread-2"
Java stack information for the threads listed above:
===================================================
"Thread-2":
at DeadLock.d(DeadLock.java:22)
- waiting to lock <0x00000000d7a20300> (a java.lang.Object)
- locked <0x00000000d7a202f0> (a java.lang.Object)
at DeadLock$2.run(DeadLock.java:42)
at java.lang.Thread.run(Thread.java:745)
"Thread-1":
at DeadLock.dead(DeadLock.java:11)
- waiting to lock <0x00000000d7a202f0> (a java.lang.Object)
- locked <0x00000000d7a20300> (a java.lang.Object)
at DeadLock$1.run(DeadLock.java:33)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
这么多线程其实我也还搞不懂,只是想帮助大家学会使用一些java的底层工具。底层的东西可以让我们更加深入的了解一门语言,写出更安全,更漂亮,更高效的代码。