gate.util.ThreadWarningSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gate-core Show documentation
Show all versions of gate-core Show documentation
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);
}
}