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

gate.util.ThreadWarningSystem Maven / Gradle / Ivy

Go to download

GATE - general achitecture for text engineering - is open source software capable of solving almost any text processing problem. This artifact enables you to embed the core GATE Embedded with its essential dependencies. You will able to use the GATE Embedded API and load and store GATE XML documents. This artifact is the perfect dependency for CREOLE plugins or for applications that need to customize the GATE dependencies due to confict with their own dependencies or for lower footprint.

The newest version!
package gate.util;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

/**
 * http://www.javaspecialists.eu/archive/Issue093.html
 */
public class ThreadWarningSystem {
  private final Timer threadCheck = new Timer("Thread Monitor", true);
  private final ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
  private final Collection listeners = new ArrayList();
  /**
   * 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 DEADLOCK_CHECK_PERIOD = 500;
  /**
   * The number of milliseconds between checking number of
   * threads.  Since threads can be created very quickly, we need
   * to check this frequently.
   */
  private static final int THREAD_NUMBER_CHECK_PERIOD = 20;
  private static final int MAX_STACK_DEPTH = 30;
  private boolean threadThresholdNotified = false;
  private Set deadlockedThreads = new HashSet();

  /**
   * Monitor only deadlocks.
   */
  public ThreadWarningSystem() {
    threadCheck.schedule(new TimerTask() {
      @Override
      public void run() {
        long[] ids = mbean.findMonitorDeadlockedThreads();
        if (ids != null && ids.length > 0) {
          for (Long l : ids) {
            if (!deadlockedThreads.contains(l)) {
              deadlockedThreads.add(l);
              ThreadInfo ti = mbean.getThreadInfo(l, MAX_STACK_DEPTH);
              fireDeadlockDetected(ti);
            }
          }
        }
      }
    }, 10, DEADLOCK_CHECK_PERIOD);
  }

  /**
   * Monitor deadlocks and the number of threads.
   */
  public ThreadWarningSystem(final int threadThreshold) {
    this();
    threadCheck.schedule(new TimerTask() {
      @Override
      public void run() {
        if (mbean.getThreadCount() > threadThreshold) {
          if (!threadThresholdNotified) {
            fireThresholdExceeded();
            threadThresholdNotified = true;
          }
        } else {
          threadThresholdNotified = false;
        }
      }
    }, 10, THREAD_NUMBER_CHECK_PERIOD);
  }

  private void fireDeadlockDetected(ThreadInfo thread) {
    // In general I avoid using synchronized.  The surrounding
    // code should usually be responsible for being threadsafe.
    // However, in this case, the timer could be notifying at
    // the same time as someone is adding a listener, and there
    // is nothing the calling code can do to prevent that from
    // occurring.  Another tip though is this: when I synchronize
    // I use a private field to synchronize on, instead of
    // "this".
    synchronized (listeners) {
      for (Listener l : listeners) {
        l.deadlockDetected(thread);
      }
    }
  }

  private void fireThresholdExceeded() {
    ThreadInfo[] allThreads = mbean.getThreadInfo(mbean.getAllThreadIds());
    synchronized (listeners) {
      for (Listener l : listeners) {
        l.thresholdExceeded(allThreads);
      }
    }
  }

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

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

  /**
   * This is called whenever a problem with threads is detected.
   * The two events are deadlockDetected() and thresholdExceeded().
   */
  public interface Listener {
    /**
     * @param deadlockedThread The deadlocked thread, with stack
     * trace of limited depth.
     */
    void deadlockDetected(ThreadInfo deadlockedThread);
    /**
     * @param allThreads All the threads in the JVM, without
     * stack traces.
     */
    void thresholdExceeded(ThreadInfo[] allThreads);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy