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

gov.nist.core.ThreadAuditor Maven / Gradle / Ivy

There is a newer version: 1.3.0-91
Show newest version
package android.gov.nist.core;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Thread Auditor class:
 *   - Provides a mechanism for applications to check the health of internal threads
 *   - The mechanism is fairly simple:
 *   - Threads register with the auditor at startup and "ping" the auditor every so often.
 *   - The application queries the auditor about the health of the system periodically. The
 *     auditor reports if the threads are healthy or if any of them failed to ping and are
 *     considered dead or stuck.
 *   - The main implication for the monitored threads is that they can no longer block
 *     waiting for an event forever. Any wait() must be implemented with a timeout so that
 *     the thread can periodically ping the auditor.
 *
 * This code is in the public domain.
 *
 * @author R. Borba (Natural Convergence)   
* @version 1.2 */ public class ThreadAuditor { /// Threads being monitored //jeand : moved to concurrent to avoid blocking witnessed by profiler private Map threadHandles = new ConcurrentHashMap(); /// How often are threads supposed to ping private long pingIntervalInMillisecs = 0; /// Internal class, used as a handle by the monitored threads public class ThreadHandle { /// Set to true when the thread pings, periodically reset to false by the auditor private boolean isThreadActive; /// Thread being monitored private Thread thread; /// Thread auditor monitoring this thread private ThreadAuditor threadAuditor; /// Constructor public ThreadHandle(ThreadAuditor aThreadAuditor) { isThreadActive = false; thread = Thread.currentThread(); threadAuditor = aThreadAuditor; } /// Called by the auditor thread to check the ping status of the thread public boolean isThreadActive() { return isThreadActive; } /// Called by the auditor thread to reset the ping status of the thread protected void setThreadActive(boolean value) { isThreadActive = value; } /// Return the thread being monitored public Thread getThread() { return thread; } // Helper function to allow threads to ping using this handle public void ping() { threadAuditor.ping(this); } // Helper function to allow threads to get the ping interval directly from this handle public long getPingIntervalInMillisecs() { return threadAuditor.getPingIntervalInMillisecs(); } /** * Returns a string representation of the object * * @return a string representation of the object */ public String toString() { StringBuilder toString = new StringBuilder() .append("Thread Name: ").append(thread.getName()) .append(", Alive: ").append(thread.isAlive()); return toString.toString(); } } /// Indicates how often monitored threads are supposed to ping (0 = no thread monitoring) public long getPingIntervalInMillisecs() { return pingIntervalInMillisecs; } /// Defines how often monitored threads are supposed to ping public void setPingIntervalInMillisecs(long value) { pingIntervalInMillisecs = value; } /// Indicates if the auditing of threads is enabled public boolean isEnabled() { return (pingIntervalInMillisecs > 0); } /// Called by a thread that wants to be monitored public ThreadHandle addCurrentThread() { // Create and return a thread handle but only add it // to the list of monitored threads if the auditor is enabled ThreadHandle threadHandle = new ThreadHandle(this); if (isEnabled()) { threadHandles.put(Thread.currentThread(), threadHandle); } return threadHandle; } /// Stops monitoring a given thread public void removeThread(Thread thread) { threadHandles.remove(thread); } /// Called by a monitored thread reporting that it's alive and well public void ping(ThreadHandle threadHandle) { threadHandle.setThreadActive(true); } /// Resets the auditor public void reset() { threadHandles.clear(); } /** * Audits the sanity of all threads * * @return An audit report string (multiple lines), or null if all is well */ public String auditThreads() { String auditReport = null; // Map stackTraces = null; // Scan all monitored threads looking for non-responsive ones Iterator it = threadHandles.values().iterator(); while (it.hasNext()) { ThreadHandle threadHandle = (ThreadHandle) it.next(); if (!threadHandle.isThreadActive()) { // Get the non-responsive thread Thread thread = threadHandle.getThread(); // Update the audit report if (auditReport == null) { auditReport = "Thread Auditor Report:\n"; } auditReport += " Thread [" + thread.getName() + "] has failed to respond to an audit request.\n"; /* * Stack traces are not available with JDK 1.4. * Feel free to uncomment this block to get a better report if you're using JDK 1.5. */ // // Get stack traces for all live threads (do this only once per audit) // if (stackTraces == null) { // stackTraces = Thread.getAllStackTraces(); // } // // // Get the stack trace for the non-responsive thread // StackTraceElement[] stackTraceElements = (StackTraceElement[])stackTraces.get(thread); // if (stackTraceElements != null && stackTraceElements.length > 0) { // auditReport += " Stack trace:\n"; // // for (int i = 0; i < stackTraceElements.length ; i ++ ) { // StackTraceElement stackTraceElement = stackTraceElements[i]; // auditReport += " " + stackTraceElement.toString() + "\n"; // } // } else { // auditReport += " Stack trace is not available.\n"; // } } // Reset the ping status of the thread threadHandle.setThreadActive(false); } return auditReport; } /** * Returns a string representation of the object * * @return a string representation of the object */ public synchronized String toString() { String toString = "Thread Auditor - List of monitored threads:\n"; Iterator it = threadHandles.values().iterator(); while ( it.hasNext()) { ThreadHandle threadHandle = (ThreadHandle)it.next(); toString += " " + threadHandle.toString() + "\n"; } return toString; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy