ThreadMXBeanクラスでプログラムのデッドロックを確認


転載先:http://www.importnew.com/15307.html
まず、この分類「技術共有」を作成した理由を明らかにします.私は特にオープンソースのコードが好きで、他の人が好きなコードを共有することにも熱中しています.素晴らしい技術を見て、いつも自分で手動で試しています.もっと多くの人がこの技術を見ることができて、後で自分が忘れないように、特に自分で手動で実践したコードを見ることができます.そして、自分がコードを書く過程で出会った疑問を記録し、オープンソースの世界のために自分の微博の力を尽くします.
ThreadMXBean
Java仮想マシンスレッドシステムの管理インタフェース.
Java仮想マシンには、このインタフェースの実装クラスの単一のインスタンスがあります.このインタフェースを実装する例は、ManagementFactory.getThreadMXBean()メソッドを呼び出すか、プラットフォームMBeanServerメソッドから取得できるMXBeanです.  MBeanServer内でスレッドシステムを一意に識別するMXBeanのObjectNameは、次のとおりです. java.lang:type=Threading 
このクラスはスレッド情報を管理するために使用されます.デッドロック状態のスレッドを検索するためのメソッドfindDeadlockedThreads()とfindMonitorDeadlockedThreads()が含まれています.
両者の違いは、findDeadlockedThreadsはowner locks(java.util.concurrent)によるデッドロックも検出することができ、findMonitorDeadlockedThreadsはmonitor locks(例えば、同期ブロック)しか検出できないことである.findDeadlockedThreadsはjava 5によって導入され、findMonitorDeadlockedThreadsはjava 6によって導入された.
プログラムの思想は周期的にデッドロックが発生しているかどうかを検査することである.コードは次のとおりです.
package org.zdnuist.demo.handlerdeadthread;

import java.lang.management.ThreadInfo;

public interface DeadlockHandler {
	
	void handleDeadLock(final ThreadInfo[] deadLockThreads);

}
package org.zdnuist.demo.handlerdeadthread;


import java.lang.management.ThreadInfo;


public class DeadlockConsoleHandler implements DeadlockHandler{


@Override
public void handleDeadLock(ThreadInfo[] deadLockThreads) {
if(deadLockThreads != null){
System.err.println("Deadlock detected!");


//Map stackTraceMap = Thread.getAllStackTraces();
for(ThreadInfo threadInfo : deadLockThreads){
if(threadInfo != null){
for(Thread thread : Thread.getAllStackTraces().keySet()){
if(thread.getId() == threadInfo.getThreadId()){
System.err.println(threadInfo.toString().trim());


for(StackTraceElement ste : thread.getStackTrace()){
System.err.println("t" + ste.toString().trim());
}
 }
}
}
}
}
}




}
package org.zdnuist.demo.handlerdeadthread;


import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class DeadlockDetector {

private final DeadlockHandler deadlockHandler;
private final long period;
private final TimeUnit unit;
private final ThreadMXBean mBean = ManagementFactory.getThreadMXBean();

private final ScheduledExecutorService schedule = 
Executors.newScheduledThreadPool(1);

public DeadlockDetector(final DeadlockHandler deadlockHandler,
final long period,final TimeUnit unit){
this.deadlockHandler = deadlockHandler;
this.period = period;
this.unit = unit;
}

final Runnable deadlockCheck = new Runnable(){


@Override
public void run() {
long[] deadlockedThreads = DeadlockDetector.this.mBean.findDeadlockedThreads();

if(deadlockedThreads != null){
ThreadInfo[] threadInfos = 
DeadlockDetector.this.mBean.getThreadInfo(deadlockedThreads);
DeadlockDetector.this.deadlockHandler.handleDeadLock(threadInfos);
}
}

};
public void start(){
this.schedule.scheduleAtFixedRate(this.deadlockCheck, this.period, this.period, this.unit);
}


}
package org.zdnuist.demo.handlerdeadthread;


import java.util.concurrent.TimeUnit;


public class Test {
public static void main(String[] args) {
DeadlockDetector deadlockDetector = new DeadlockDetector(new DeadlockConsoleHandler(),5,TimeUnit.SECONDS);
deadlockDetector.start();
final Object lock1 = new Object();
final Object lock2 = new Object();

Thread thread1 = new Thread(){
@Override
public void run() {
synchronized (lock1) {
System.out.println("Thread1 acquired lock1");

try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread1 acquired lock2");
}
}
}
};
thread1.setName("Thread_1");
thread1.start();

Thread thread2 = new Thread(){
public void run(){
synchronized (lock2) {
System.out.println("Thread2 acquired lock2");

synchronized (lock1) {
System.out.println("Thread2 acquired lock1");
}
}
}
};
thread2.setName("Thread_2");
thread2.start();
}


}

終了:
デッドロック検出のオーバーヘッドが大きい可能性があります.プログラムを使用して、本当にデッドロック検出が必要かどうか、どのくらい検出するかをテストする必要があります.デッドロック検出の間隔は少なくとも数分であることをお勧めします.より頻繁な検出はあまり意味がありません.なぜなら、復元計画がないからです.デバッグやエラーの処理、プログラムの再起動だけで、デッドロックが再発しないことを祈ることができます.デッドロックの問題を解決するための良いアドバイスや、この解決策についての疑問があれば、以下にメッセージを残してください.