All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.cedarsoft.utils.lock.ThreadDeadlockDetector Maven / Gradle / Ivy

The newest version!
package eu.cedarsoft.utils.lock;

import org.jetbrains.annotations.NotNull;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 *
 */
public class ThreadDeadlockDetector {
  @NotNull
  private final Timer threadCheck = new Timer( "ThreadDeadlockDetector", true );
  @NotNull
  private final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
  @NotNull
  private final Collection listeners = new CopyOnWriteArraySet();

  /**
   * The number of milliseconds between checking for deadlocks.
   * It may be expensive to check for deadlocks, and it is not
   * critical to know so quickly.
   */
  private static final int DEFAULT_DEADLOCK_CHECK_PERIOD = 10000;

  public ThreadDeadlockDetector() {
    this( DEFAULT_DEADLOCK_CHECK_PERIOD );
  }

  public ThreadDeadlockDetector( int deadlockCheckPeriod ) {
    threadCheck.schedule( new TimerTask() {
      @Override
      public void run() {
        checkForDeadlocks();
      }
    }, 10, deadlockCheckPeriod );
  }

  private void checkForDeadlocks() {
    long[] ids = findDeadlockedThreads();
    if ( ids != null && ids.length > 0 ) {
      Thread[] threads = new Thread[ids.length];
      for ( int i = 0; i < threads.length; i++ ) {
        threads[i] = findMatchingThread( mbean.getThreadInfo( ids[i] ) );
      }
      fireDeadlockDetected( threads );
    }
  }

  private long[] findDeadlockedThreads() {
    // JDK 1.5 only supports the findMonitorDeadlockedThreads()
    // method, so you need to comment out the following three lines
    if ( mbean.isSynchronizerUsageSupported() ) {
      return mbean.findDeadlockedThreads();
    } else {
      return mbean.findMonitorDeadlockedThreads();
    }
  }

  private void fireDeadlockDetected( Thread[] threads ) {
    for ( Listener l : listeners ) {
      l.deadlockDetected( threads );
    }
  }

  private static Thread findMatchingThread( ThreadInfo inf ) {
    for ( Thread thread : Thread.getAllStackTraces().keySet() ) {
      if ( thread.getId() == inf.getThreadId() ) {
        return thread;
      }
    }
    throw new IllegalStateException( "Deadlocked Thread not found" );
  }

  public boolean addListener( Listener l ) {
    return listeners.add( l );
  }

  public boolean removeListener( Listener l ) {
    return listeners.remove( l );
  }

  /**
   * This is called whenever a problem with threads is detected.
   */
  public interface Listener {
    void deadlockDetected( Thread[] deadlockedThreads );
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy