ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = tmx.dumpAllThreads(true, true);
通过上面的代码,我们可以将jvm进程的所有线程及堆栈dump下来。我们可以看到dump方法有两个参数: dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers)
这两个参数分别控制两种锁ThreadInfo .getLockedMonitors() 和ThreadInfo.getLockedSynchronizers()
a. Monitor 锁
就是我们传统使用的synchronized(Object obj),可以通过MonitorInfo[]得到具体的锁的数量和信息
- 如果项目中使用synchronized,在dumpAllThreads第一个参数设置为true,就可以通过ThreadInfo.getLockedMonitors()获取线程持有的monitor
- 相反如果一个参数设置为false,ThreadInfo.getLockedMonitors()这个就会返回为空
b. Locked ownable synchronizers 锁
常指的ReentrantLock 和 ReentrantReadWriteLock 锁
通过得到LockInfo[] 可以得到具体的类,锁的数量和信息
- 如果项目中使用ReentrantLock,在dumpAllThreads第二个参数设置为true,就可以通过ThreadInfo.getLockedSynchronizers()获取线程持有的该类型锁。
- 相反如果第二个参数设置为false,ThreadInfo.getLockedSynchronizers()这个就会返回为空
注意
ThreadMXBean.dumpAllThreads(true,true)因为要获取所有jvm线程的monitor和synchronizer信息,会挂起执行线程。对负载较大的服务器端程序,会引起latency飙升
下面我们通过一个示例看一下两个参数作用
public class RtTest {
public static void main(String[] args) {
final RtTest rt = new RtTest();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
rt.processLock();
}
});
t.start();
}
final RtTest rt2 = new RtTest();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
rt2.processSync();
}
});
t.start();
}
ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = tmx.dumpAllThreads(true, true);
for (ThreadInfo threadInfo : threadInfos) {
System.out.println(threadInfo);
}
System.out.println("hhhhhhhhhh");
for (ThreadInfo threadInfo : threadInfos) {
for (MonitorInfo lockedMonitor : threadInfo.getLockedMonitors()) {
System.out.println(threadInfo.getThreadName()+":");
System.out.println(lockedMonitor);
}
}
System.out.println("oooooooo");
for (ThreadInfo threadInfo : threadInfos) {
for (LockInfo lockedSynchronizer : threadInfo.getLockedSynchronizers()) {
System.out.println(threadInfo.getThreadName()+":");
System.out.println(lockedSynchronizer);
}
}
}
public synchronized int processLock(){
int l =0;
for (int i = 0; i < 1000*1000*1000; i++) {
l += i*i;
}
return l;
}
public synchronized void processSync(){
ReentrantLock reentrantLock = new ReentrantLock();
reentrantLock.lock();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
reentrantLock.unlock();
}
结果输出如下:
"Thread-3" Id=14 BLOCKED on RtTest@2626b418 owned by "Thread-2" Id=13
at RtTest.processSync(RtTest.java:69)
- blocked on RtTest@2626b418
at RtTest$2.run(RtTest.java:28)
at java.lang.Thread.run(Thread.java:745)
"Thread-2" Id=13 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at RtTest.processSync(RtTest.java:72)
- locked RtTest@2626b418
at RtTest$2.run(RtTest.java:28)
at java.lang.Thread.run(Thread.java:745)
Number of locked synchronizers = 1
- java.util.concurrent.locks.ReentrantLock$NonfairSync@5a07e868
"Thread-1" Id=12 BLOCKED on RtTest@76ed5528 owned by "Thread-0" Id=11
at RtTest.processLock(RtTest.java:61)
- blocked on RtTest@76ed5528
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" Id=11 RUNNABLE
at RtTest.processLock(RtTest.java:62)
- locked RtTest@76ed5528
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)
"Monitor Ctrl-Break" Id=5 RUNNABLE
at java.net.NetworkInterface.init(Native Method)
at java.net.NetworkInterface.(NetworkInterface.java:64)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
- locked java.net.SocksSocketImpl@2c7b84de
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
...
"Signal Dispatcher" Id=4 RUNNABLE
"Finalizer" Id=3 WAITING on java.lang.ref.ReferenceQueue$Lock@3fee733d
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.ReferenceQueue$Lock@3fee733d
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" Id=2 WAITING on java.lang.ref.Reference$Lock@5acf9800
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@5acf9800
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
"main" Id=1 RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:446)
at RtTest.main(RtTest.java:35)
hhhhhhhhhh
Thread-2:
RtTest@2626b418
Thread-0:
RtTest@76ed5528
Monitor Ctrl-Break:
java.net.SocksSocketImpl@2c7b84de
oooooooo
Thread-2:
java.util.concurrent.locks.ReentrantLock$NonfairSync@5a07e868
如果我们dump参数全部设置为false,即: ThreadInfo[] threadInfos = tmx.dumpAllThreads(false, false); 结果如下:
"Thread-3" Id=14 BLOCKED on RtTest@2626b418 owned by "Thread-2" Id=13
at RtTest.processSync(RtTest.java:69)
- blocked on RtTest@2626b418
at RtTest$2.run(RtTest.java:28)
at java.lang.Thread.run(Thread.java:745)
"Thread-2" Id=13 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at RtTest.processSync(RtTest.java:72)
at RtTest$2.run(RtTest.java:28)
at java.lang.Thread.run(Thread.java:745)
"Thread-1" Id=12 BLOCKED on RtTest@5a07e868 owned by "Thread-0" Id=11
at RtTest.processLock(RtTest.java:61)
- blocked on RtTest@5a07e868
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" Id=11 RUNNABLE
at RtTest.processLock(RtTest.java:62)
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)
"Monitor Ctrl-Break" Id=5 RUNNABLE
at java.lang.ClassLoader$NativeLibrary.find(Native Method)
at java.lang.ClassLoader.findNative(ClassLoader.java:1960)
at java.net.NetworkInterface.getAll(Native Method)
at java.net.NetworkInterface.getNetworkInterfaces(NetworkInterface.java:343)
at java.net.DefaultInterface.chooseDefaultInterface(DefaultInterface.java:67)
at java.net.DefaultInterface.(DefaultInterface.java:46)
at java.net.NetworkInterface.(NetworkInterface.java:65)
at java.net.PlainSocketImpl.socketConnect(Native Method)
...
"Signal Dispatcher" Id=4 RUNNABLE
"Finalizer" Id=3 WAITING on java.lang.ref.ReferenceQueue$Lock@76ed5528
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.ReferenceQueue$Lock@76ed5528
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" Id=2 WAITING on java.lang.ref.Reference$Lock@2c7b84de
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@2c7b84de
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
"main" Id=1 RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:446)
at RtTest.main(RtTest.java:35)
hhhhhhhhhh
oooooooo
区别:
- 获取不到Monitor和synchronizers锁信息了。
- Thread-0、Thread-2的堆栈信息(此时两个线程正在运行,持有了该锁),不再显示锁信息。如下所示,缺少了lock
"Thread-0" Id=11 RUNNABLE
at RtTest.processLock(RtTest.java:62)
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" Id=11 RUNNABLE
at RtTest.processLock(RtTest.java:62)
- locked RtTest@76ed5528
at RtTest$1.run(RtTest.java:17)
at java.lang.Thread.run(Thread.java:745)