package evanq.game.helper; import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; import java.lang.management.MonitorInfo; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import evanq.game.errno.ExitCode; import evanq.game.utils.ExceptionUtils; /** * * 死锁监听器 * * @author Evan * */ public class DeadLockDetector extends Thread { /** 出现死锁,什么都不做 */ public static final byte NOTHING = 0; /** 出现死锁,重新启动 */ public static final byte RESTART = 1; /** 检测死锁的时间间隔 */ private final int sleepTime; /** * ThreadMXBean */ private final ThreadMXBean tmx; private final byte doWhenDL; public DeadLockDetector(int sleepTime, byte doWhenDL) { super("DeadLockDetector"); this.sleepTime = sleepTime * 1000; this.tmx = ManagementFactory.getThreadMXBean(); this.doWhenDL = doWhenDL; } @Override public synchronized void run() { boolean deadlock = false; while (!deadlock) { try { long[] ids = tmx.findDeadlockedThreads(); if (ids != null) { /** deadlock found :/ */ deadlock = true; ThreadInfo[] tis = tmx.getThreadInfo(ids, true, true); String info = "DeadLock Found!\n"; for (ThreadInfo ti : tis) { info += ti.toString(); } for (ThreadInfo ti : tis) { LockInfo[] locks = ti.getLockedSynchronizers(); MonitorInfo[] monitors = ti.getLockedMonitors(); if (locks.length == 0 && monitors.length == 0) { /** this thread is deadlocked but its not guilty */ continue; } ThreadInfo dl = ti; info += "Java-level deadlock:\n"; info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n"; while ((dl = tmx.getThreadInfo( new long[] { dl.getLockOwnerId() }, true, true)[0]) .getThreadId() != ti.getThreadId()) { info += "\t" + dl.getThreadName() + " is waiting to lock " + dl.getLockInfo().toString() + " which is held by " + dl.getLockOwnerName() + "\n"; } } ExceptionUtils.getTrace().error(info); if (doWhenDL == RESTART) { System.exit(ExitCode.CODE_RESTART); } } Thread.sleep(sleepTime); } catch (Exception e) { ExceptionUtils.getTrace().error("{}",e); } } } }