ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
ThreadInfo[] threadInfos = tmx.dumpAllThreads(true, true);
通過上面的代碼,我們可以將jvm進(jìn)程的所有線程及堆棧dump下來洗鸵。我們可以看到dump方法有兩個(gè)參數(shù): dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers)
這兩個(gè)參數(shù)分別控制兩種鎖ThreadInfo .getLockedMonitors() 和ThreadInfo.getLockedSynchronizers()
a. Monitor 鎖
就是我們傳統(tǒng)使用的synchronized(Object obj),可以通過MonitorInfo[]得到具體的鎖的數(shù)量和信息
- 如果項(xiàng)目中使用synchronized幢痘,在dumpAllThreads第一個(gè)參數(shù)設(shè)置為true瀑踢,就可以通過ThreadInfo.getLockedMonitors()獲取線程持有的monitor
- 相反如果一個(gè)參數(shù)設(shè)置為false辨宠,ThreadInfo.getLockedMonitors()這個(gè)就會(huì)返回為空
b. Locked ownable synchronizers 鎖
常指的ReentrantLock 和 ReentrantReadWriteLock 鎖
通過得到LockInfo[] 可以得到具體的類,鎖的數(shù)量和信息
- 如果項(xiàng)目中使用ReentrantLock琳省,在dumpAllThreads第二個(gè)參數(shù)設(shè)置為true迎吵,就可以通過ThreadInfo.getLockedSynchronizers()獲取線程持有的該類型鎖。
- 相反如果第二個(gè)參數(shù)設(shè)置為false针贬,ThreadInfo.getLockedSynchronizers()這個(gè)就會(huì)返回為空
注意
ThreadMXBean.dumpAllThreads(true,true)因?yàn)橐@取所有jvm線程的monitor和synchronizer信息击费,會(huì)掛起執(zhí)行線程。對(duì)負(fù)載較大的服務(wù)器端程序桦他,會(huì)引起latency飆升
下面我們通過一個(gè)示例看一下兩個(gè)參數(shù)作用
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();
}
結(jié)果輸出如下:
"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.<clinit>(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參數(shù)全部設(shè)置為false蔫巩,即: ThreadInfo[] threadInfos = tmx.dumpAllThreads(false, false); 結(jié)果如下:
"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.<clinit>(DefaultInterface.java:46)
at java.net.NetworkInterface.<clinit>(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
區(qū)別:
- 獲取不到Monitor和synchronizers鎖信息了。
- Thread-0、Thread-2的堆棧信息(此時(shí)兩個(gè)線程正在運(yùn)行圆仔,持有了該鎖)垃瞧,不再顯示鎖信息。如下所示坪郭,缺少了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)