Java/Threads/Utilities

Материал из Java эксперт
Перейти к: навигация, поиск

Busy Flag

   <source lang="java">
 

/*

*
* Copyright (c) 1997-1999 Scott Oaks and Henry Wong. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and
* without fee is hereby granted.
*
* This sample source code is provided for example only,
* on an unsupported, as-is basis. 
*
* AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. AUTHOR SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  AUTHOR
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/

public class BusyFlag {

 protected Thread busyflag = null;
 protected int busycount = 0;
 public synchronized void getBusyFlag() {
   while (tryGetBusyFlag() == false) {
     try {
       wait();
     } catch (Exception e) {}
   }
 }
 public synchronized boolean tryGetBusyFlag() {
   if (busyflag == null) {
     busyflag = Thread.currentThread();
     busycount = 1;
     return true;
   }
   if (busyflag == Thread.currentThread()) {
     busycount++;
     return true;
   }
   return false;
 }
 public synchronized void freeBusyFlag() {
   if (getBusyFlagOwner() == Thread.currentThread()) {
     busycount--;
     if (busycount == 0) {
       busyflag = null;
       notify();
     }
   }
 }
 public synchronized Thread getBusyFlagOwner() {
   return busyflag;
 }

} /*

*
* Copyright (c) 1997-1999 Scott Oaks and Henry Wong. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and
* without fee is hereby granted.
*
* This sample source code is provided for example only,
* on an unsupported, as-is basis. 
*
* AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. AUTHOR SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  AUTHOR
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/

public class CondVar {

       private BusyFlag SyncVar;
       public CondVar() {
               this(new BusyFlag());
       }
       public CondVar(BusyFlag sv) {
               SyncVar = sv;
       }
       public void cvWait() throws InterruptedException {
               cvTimedWait(SyncVar, 0);
       }
       public void cvWait(BusyFlag sv) throws InterruptedException {
               cvTimedWait(sv, 0);
       }
       public void cvTimedWait(int millis) throws InterruptedException {
               cvTimedWait(SyncVar, millis);
       }
       public void cvTimedWait(BusyFlag sv, int millis) throws InterruptedException {
               int i = 0;
               InterruptedException errex = null;
               synchronized (this) {
                       // You must own the lock in order to use this method
                       if (sv.getBusyFlagOwner() != Thread.currentThread()) {
                               throw new IllegalMonitorStateException("current thread not owner");
                       }
                       // Release the lock (Completely)
                       while (sv.getBusyFlagOwner() == Thread.currentThread()) {
                               i++;
                               sv.freeBusyFlag();
                       }
               
                       // Use wait() method        
                       try {
                               if (millis == 0) {
                                       wait();
                               } else {
                                       wait(millis);
                               }
                       } catch (InterruptedException iex) {
                               errex = iex;
                       }
               }
        
               // Obtain the lock (Return to original state)
               for (; i>0; i--) {
                       sv.getBusyFlag();
               }
               if (errex != null) throw errex;
               return;
       }
       public void cvSignal() {
               cvSignal(SyncVar);
       }
       public synchronized void cvSignal(BusyFlag sv) {
               // You must own the lock in order to use this method
               if (sv.getBusyFlagOwner() != Thread.currentThread()) {
                       throw new IllegalMonitorStateException("current thread not owner");
               }
               notify();
       }
       public void cvBroadcast() {
               cvBroadcast(SyncVar);
       }
       public synchronized void cvBroadcast(BusyFlag sv) {
               // You must own the lock in order to use this method
               if (sv.getBusyFlagOwner() != Thread.currentThread()) {
                       throw new IllegalMonitorStateException("current thread not owner");
               }
               notifyAll();
       }

}



 </source>
   
  
 
  



Early return

   <source lang="java">
 

public class EarlyReturn extends Object {

 private volatile int value;
 public EarlyReturn(int v) {
   value = v;
 }
 public synchronized void setValue(int v) {
   if (value != v) {
     value = v;
     notifyAll();
   }
 }
 public synchronized boolean waitUntilAtLeast(int minValue, long msTimeout)
     throws InterruptedException {
   System.out.println("value=" + value + ",minValue=" + minValue);
   long endTime = System.currentTimeMillis() + msTimeout;
   long msRemaining = msTimeout;
   while ((value < minValue) && (msRemaining > 0L)) {
     System.out.println("about to: wait(" + msRemaining + ")");
     wait(msRemaining);
     msRemaining = endTime - System.currentTimeMillis();
     System.out.println("back from wait(), new msRemaining="
         + msRemaining);
   }
   System.out.println("leaving waitUntilAtLeast() - " + "value=" + value
       + ",minValue=" + minValue);
   // May have timed out, or may have met value,
   return (value >= minValue);
 }
 public static void main(String[] args) {
   try {
     final EarlyReturn er = new EarlyReturn(0);
     Runnable r = new Runnable() {
       public void run() {
         try {
           Thread.sleep(1500);
           er.setValue(2);
           Thread.sleep(500);
           er.setValue(3);
           Thread.sleep(500);
           er.setValue(4);
         } catch (Exception x) {
           x.printStackTrace();
         }
       }
     };
     Thread t = new Thread(r);
     t.start();
     System.out.println("waitUntilAtLeast(5, 3000)");
     long startTime = System.currentTimeMillis();
     boolean retVal = er.waitUntilAtLeast(5, 3000);
     long elapsedTime = System.currentTimeMillis() - startTime;
     System.out.println(elapsedTime + " ms, retVal=" + retVal);
   } catch (InterruptedException ix) {
     ix.printStackTrace();
   }
 }

}


 </source>
   
  
 
  



Exception call back

   <source lang="java">
 

import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class ExceptionCallbackMain extends Object implements ExceptionListener {

 private int exceptionCount;
 public ExceptionCallbackMain() {
   exceptionCount = 0;
 }
 public void exceptionOccurred(Exception x, Object source) {
   exceptionCount++;
   System.err.println("EXCEPTION #" + exceptionCount + ", source="
       + source);
   x.printStackTrace();
 }
 public static void main(String[] args) {
   ExceptionListener xListener = new ExceptionCallbackMain();
   ExceptionCallback ec = new ExceptionCallback(xListener);
 }

} class ExceptionCallback extends Object {

 private Set exceptionListeners;
 private Thread internalThread;
 private volatile boolean noStopRequested;
 public ExceptionCallback(ExceptionListener[] initialGroup) {
   init(initialGroup);
 }
 public ExceptionCallback(ExceptionListener initialListener) {
   ExceptionListener[] group = new ExceptionListener[1];
   group[0] = initialListener;
   init(group);
 }
 public ExceptionCallback() {
   init(null);
 }
 private void init(ExceptionListener[] initialGroup) {
   System.out.println("initializing...");
   exceptionListeners = Collections.synchronizedSet(new HashSet());
   if (initialGroup != null) {
     for (int i = 0; i < initialGroup.length; i++) {
       addExceptionListener(initialGroup[i]);
     }
   }
   noStopRequested = true;
   Runnable r = new Runnable() {
     public void run() {
       try {
         runWork();
       } catch (Exception x) {
         sendException(x);
       }
     }
   };
   internalThread = new Thread(r);
   internalThread.start();
 }
 private void runWork() {
   try {
     makeConnection(); 
   } catch (IOException x) {
     sendException(x);
   }
   String str = null;
   int len = determineLength(str); 
 }
 private void makeConnection() throws IOException {
   String portStr = "jexp20";
   int port = 0;
   try {
     port = Integer.parseInt(portStr);
   } catch (NumberFormatException x) {
     sendException(x);
     port = 80;
   }
   connectToPort(port); 
 }
 private void connectToPort(int portNum) throws IOException {
   throw new IOException("connection refused");
 }
 private int determineLength(String s) {
   return s.length();
 }
 public void stopRequest() {
   noStopRequested = false;
   internalThread.interrupt();
 }
 public boolean isAlive() {
   return internalThread.isAlive();
 }
 private void sendException(Exception x) {
   if (exceptionListeners.size() == 0) {
     x.printStackTrace();
     return;
   }
   synchronized (exceptionListeners) {
     Iterator iter = exceptionListeners.iterator();
     while (iter.hasNext()) {
       ExceptionListener l = (ExceptionListener) iter.next();
       l.exceptionOccurred(x, this);
     }
   }
 }
 public void addExceptionListener(ExceptionListener l) {
   if (l != null) {
     exceptionListeners.add(l);
   }
 }
 public void removeExceptionListener(ExceptionListener l) {
   exceptionListeners.remove(l);
 }
 public String toString() {
   return getClass().getName() + "[isAlive()=" + isAlive() + "]";
 }

} interface ExceptionListener {

 public void exceptionOccurred(Exception x, Object source);

}


 </source>
   
  
 
  



Finds a resource with the given name.

   <source lang="java">

/*

* Copyright  2003-2008 The Apache Software Foundation.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

import java.io.InputStream; /**

*
*  @author 
*  @version $Id: ClassUtils.java 685685 2008-08-13 21:43:27Z nbubna $
* @since 1.5
*/

public class Main {

 /**
  * Finds a resource with the given name.  Checks the Thread Context
  * classloader, then uses the System classloader.  Should replace all
  * calls to Class.getResourceAsString when the resource
  * might come from a different classloader.  (e.g. a webapp).
  * @param claz Class to use when getting the System classloader (used if no Thread
  * Context classloader available or fails to get resource).
  * @param name name of the resource
  * @return InputStream for the resource.
  */
 public static InputStream getResourceAsStream(Class claz, String name)
 {
     InputStream result = null;
     /**
      * remove leading slash so path will work with classes in a JAR file
      */
     while (name.startsWith("/"))
     {
         name = name.substring(1);
     }
     ClassLoader classLoader = Thread.currentThread()
                                 .getContextClassLoader();
     if (classLoader == null)
     {
         classLoader = claz.getClassLoader();
         result = classLoader.getResourceAsStream( name );
     }
     else
     {
         result= classLoader.getResourceAsStream( name );
         /**
         * for compatibility with texen / ant tasks, fall back to
         * old method when resource is not found.
         */
         if (result == null)
         {
             classLoader = claz.getClassLoader();
             if (classLoader != null)
                 result = classLoader.getResourceAsStream( name );
         }
     }
     return result;
 }

}

 </source>
   
  
 
  



Listing all threads and threadgroups in the VM.

   <source lang="java">
 

public class ThreadLister {

 private static void printThreadInfo(Thread t, String indent) {
   if (t == null)
     return;
   System.out.println(indent + "Thread: " + t.getName() + "  Priority: "
       + t.getPriority() + (t.isDaemon() ? " Daemon" : "")
       + (t.isAlive() ? "" : " Not Alive"));
 }
 /** Display info about a thread group */
 private static void printGroupInfo(ThreadGroup g, String indent) {
   if (g == null)
     return;
   int numThreads = g.activeCount();
   int numGroups = g.activeGroupCount();
   Thread[] threads = new Thread[numThreads];
   ThreadGroup[] groups = new ThreadGroup[numGroups];
   g.enumerate(threads, false);
   g.enumerate(groups, false);
   System.out.println(indent + "Thread Group: " + g.getName()
       + "  Max Priority: " + g.getMaxPriority()
       + (g.isDaemon() ? " Daemon" : ""));
   for (int i = 0; i < numThreads; i++)
     printThreadInfo(threads[i], indent + "    ");
   for (int i = 0; i < numGroups; i++)
     printGroupInfo(groups[i], indent + "    ");
 }
 /** Find the root thread group and list it recursively */
 public static void listAllThreads() {
   ThreadGroup currentThreadGroup;
   ThreadGroup rootThreadGroup;
   ThreadGroup parent;
   // Get the current thread group
   currentThreadGroup = Thread.currentThread().getThreadGroup();
   // Now go find the root thread group
   rootThreadGroup = currentThreadGroup;
   parent = rootThreadGroup.getParent();
   while (parent != null) {
     rootThreadGroup = parent;
     parent = parent.getParent();
   }
   printGroupInfo(rootThreadGroup, "");
 }
 public static void main(String[] args) {
   ThreadLister.listAllThreads();
 }

}


 </source>
   
  
 
  



Return a new instance of the given class. Checks the ThreadContext classloader first, then uses the System classloader.

   <source lang="java">

/*

* Copyright  2003-2008 The Apache Software Foundation.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

import java.io.InputStream; /**

*
*  @author 
*  @version $Id: ClassUtils.java 685685 2008-08-13 21:43:27Z nbubna $
* @since 1.5
*/

public class Main {

 /**
  * Return a new instance of the given class.  Checks the ThreadContext
  * classloader first, then uses the System classloader.  Should replace all
  * calls to Class.forName( claz ).newInstance() (which only
  * calls the System class loader) when the class might be in a different
  * classloader (e.g. in a webapp).
  *
  * @param clazz the name of the class to instantiate
  * @return an instance of the specified class
  * @throws ClassNotFoundException
  * @throws IllegalAccessException
  * @throws InstantiationException
  */
 public static Object getNewInstance(String clazz)
     throws ClassNotFoundException,IllegalAccessException,InstantiationException
 {
     return getClass(clazz).newInstance();
 }
 /**
  * Return the specified class.  Checks the ThreadContext classloader first,
  * then uses the System classloader.  Should replace all calls to
  * Class.forName( claz ) (which only calls the System class
  * loader) when the class might be in a different classloader (e.g. in a
  * webapp).
  *
  * @param clazz the name of the class to instantiate
  * @return the requested Class object
  * @throws ClassNotFoundException
  */
 public static Class getClass(String clazz) throws ClassNotFoundException
 {
     /**
      * Use the Thread context classloader if possible
      */
     ClassLoader loader = Thread.currentThread().getContextClassLoader();
     if (loader != null)
     {
         try
         {
             return Class.forName(clazz, true, loader);
         }
         catch (ClassNotFoundException E)
         {
             /**
              * If not found with ThreadContext loader, fall thru to
              * try System classloader below (works around bug in ant).
              */
         }
     }
     /**
      * Thread context classloader isn"t working out, so use system loader.
      */
     return Class.forName(clazz);
 }

}

 </source>
   
  
 
  



Sleep utilities

   <source lang="java">
 

public final class TimerUtil {

 public final static void wait(int waitTime)
 {
   try {
     Thread.sleep(waitTime);
   }
   catch (Exception e) {}
 }
 public final static void waitRandom(int time)
 {
   int waitTime = (int)(Math.random() * (double)time);   
   try {
     Thread.sleep(waitTime);
   }
   catch (Exception e) {}
 }

}


 </source>
   
  
 
  



Thread-based logging utility

   <source lang="java">
 

/*

* Copyright Aduna (http://www.aduna-software.ru/) (c) 1997-2006.
*
* Licensed under the Aduna BSD-style license.
*/

import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; /**

* Thread-based logging utility. The ThreadLog requires threads to register
* themselves with the ThreadLog. In this registration procedure, a mapping is
* made between the thread calling the registration method and an instance of
* ThreadLog. This mapping is later used in all calls to logging-methods to
* look-up whether these messages should be logged, and where they should be
* logged.
*

* Log messages are assigned a "level of importance". From high to low, these * levels are ERROR, WARNING, STATUS and TRACE. Messages can be suppressed based * on these levels. If a Thread registers itself with log level WARNING, only * errors and warning will be logged; status messages and traces will be * suppressed. */ public class ThreadLog { /*-----------* * Constants * *-----------*/ public static final int NONE = 0; public static final int ERROR = 1; public static final int WARNING = 2; public static final int STATUS = 3; public static final int TRACE = 4; public static final int ALL = 5; private static final String LINE_SEPARATOR = System.getProperty("line.separator"); /*------------------* * Static variables * *------------------*/ static SimpleDateFormat _formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); static String[] _levelNames = { "NONE ", "ERROR ", "WARNING", "STATUS ", "TRACE ", "ALL " }; /** Keeps track of which Threads maps to which ThreadLogs. */ static InheritableThreadLocal<ThreadLog> _threadContext = new InheritableThreadLocal<ThreadLog>(); static ThreadLog _defaultThreadLog; /** Maps (absolute) file paths to PrintWriters. */ static HashMap<String, Writer> _writerTable = new HashMap<String, Writer>(); /** * set the ThreadLog to log warning and error messages to System.err by * default */ static { setDefaultLog(null, WARNING); } /*----------------* * Static methods * *----------------*/ /** * Sets a default log file for all threads that have not registered * themselves. Logging calls from any of these threads to ThreadLog will be * logged to the specified log file if their priority is equal to or higher * then the specified log level. If "logFile" is equal to "null", messages * will be printed to System.err. * * @param logFile * The file to log to, or null to log messages to * System.err. * @param logLevel * One of the constants ERROR, WARNING, STATUS, TRACE, or ALL. * @see #ERROR * @see #WARNING * @see #STATUS * @see #TRACE * @see #ALL */ public static void setDefaultLog(String logFile, int logLevel) { if (_defaultThreadLog == null) { _defaultThreadLog = new ThreadLog(); } Writer logWriter = null; try { logWriter = _getLogWriter(logFile); } catch (IOException e) { System.err.println(e.getMessage()); e.printStackTrace(); try { logWriter = _getLogWriter(null); } catch (IOException ignore) { // ignore } } _defaultThreadLog.setLogWriter(logWriter); _defaultThreadLog.setLogLev(logLevel); } /** * Unsets the default log file for all threads that have not registered * themselves. */ public static void unsetDefaultLog() { _defaultThreadLog = null; } public static int getDefaultLogLevel() { if (_defaultThreadLog == null) { _defaultThreadLog = new ThreadLog(); } return _defaultThreadLog.getLogLev(); } /** * Registers the calling thread with the ThreadLog. Logging calls to * ThreadLog will be logged to the specified log file if their priority is * equal to or higher then the specified log level. If "logFile" is equal to * "null", messages will be printed to System.err. * * @param logFile * The file to log to, or null to log messages to * System.err. * @param logLevel * One of the constants ERROR, WARNING, STATUS, TRACE, or ALL. * @see #ERROR * @see #WARNING * @see #STATUS * @see #TRACE * @see #ALL */ public static void registerThread(String logFile, int logLevel) { ThreadLog threadLog = _createThreadLog(); Writer logWriter = null; try { logWriter = _getLogWriter(logFile); } catch (IOException e) { System.err.println(e.getMessage()); e.printStackTrace(); try { logWriter = _getLogWriter(null); } catch (IOException ignore) { // ignore } } threadLog.setLogWriter(logWriter); threadLog.setLogLev(logLevel); Thread currentThread = Thread.currentThread(); threadLog.setThreadName(currentThread.getName()); } /** * Changes the log level for the calling thread. * * @param logLevel * One of the constants ERROR, WARNING, STATUS, TRACE, or ALL. * @see #ERROR * @see #WARNING * @see #STATUS * @see #TRACE */ public static void setLogLevel(int logLevel) { ThreadLog threadLog = null; synchronized (_threadContext) { threadLog = _threadContext.get(); } if (threadLog != null) { threadLog.setLogLev(logLevel); } } public static int getLogLevel() { ThreadLog threadLog = _getThreadLog(); if (threadLog != null) { return threadLog._logLevel; } else { return NONE; } } public static boolean logLevelEnabled(int logLevel) { return getLogLevel() >= logLevel; } /** * Creates a ThreadLog for the thread calling this method. If the thread has * already created a ThreadLog before, this existing ThreadLog will be * returned. */ static ThreadLog _createThreadLog() { ThreadLog threadLog = null; synchronized (_threadContext) { threadLog = _threadContext.get(); if (threadLog == null) { threadLog = new ThreadLog(); _threadContext.set(threadLog); } } return threadLog; } /** * Gets a (possibly shared) Writer to the specified logFile. */ static Writer _getLogWriter(String logFile) throws IOException { Writer logWriter = null; String absPath = null; File file = null; if (logFile != null) { file = new File(logFile); absPath = file.getAbsolutePath(); } synchronized (_writerTable) { logWriter = _writerTable.get(absPath); if (logWriter == null) { // Create a new log writer if (absPath != null) { // Check if parent directory exists yet if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } logWriter = new FileWriter(absPath, true); } else { logWriter = new OutputStreamWriter(System.err); } _writerTable.put(absPath, logWriter); } } return logWriter; } /** * Deregisters the calling thread with the ThreadLog. Logging calls to * ThreadLog on the calling thread will no longer be logged. */ public static void deregisterThread() { synchronized (_threadContext) { _threadContext.set(null); } } /** * Gets the ThreadLog for the thread calling this method. If no ThreadLog is * available, null will be returned. */ static ThreadLog _getThreadLog() { ThreadLog threadLog = null; synchronized (_threadContext) { threadLog = _threadContext.get(); } if (threadLog == null) { threadLog = _defaultThreadLog; } return threadLog; } /*-----------* * Variables * *-----------*/ /** Writer for the log file. */ Writer _logWriter; /** Log level */ int _logLevel; /** * Name of the thread. */ String _threadName; /*--------------* * Constructors * *--------------*/ ThreadLog() { this(null, ALL); } ThreadLog(Writer logWriter) { this(logWriter, ALL); } ThreadLog(Writer logWriter, int logLevel) { setLogWriter(logWriter); setLogLev(logLevel); _threadName = null; } /*---------* * Methods * *---------*/ void setLogWriter(Writer logWriter) { _logWriter = logWriter; } void setLogLev(int logLevel) { _logLevel = logLevel; } int getLogLev() { return _logLevel; } void setThreadName(String threadName) { _threadName = threadName; } String getThreadName() { return _threadName; } void doLog(String msg, Object arg, int level) { // First check log level if (_logLevel < level) { return; } // Create log message String logMsg = _createLogMessage(msg, arg, level, _threadName); // Write log message // Synchronize on _logWriter to prevent mixed lines try { synchronized (_logWriter) { _logWriter.write(logMsg); _logWriter.flush(); } } catch (Exception e) { e.printStackTrace(); } } static String _createLogMessage(String msg, Object arg, int level, String threadName) { StringBuilder logMsg = new StringBuilder(128); logMsg.append(_formatter.format(new Date())); if (threadName != null) { logMsg.append(" ["); logMsg.append(threadName); logMsg.append("]"); } logMsg.append(" ["); logMsg.append(_levelNames[level]); logMsg.append("] "); logMsg.append(msg); if (arg != null) { logMsg.append(": "); if (arg instanceof Throwable) { Throwable throwable = (Throwable)arg; logMsg.append(throwable.getMessage()); logMsg.append(LINE_SEPARATOR); java.io.StringWriter stackTrace = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(stackTrace); throwable.printStackTrace(pw); logMsg.append(stackTrace.toString()); } else { String argString = arg.toString(); if (argString.contains("\n") || argString.contains("\r")) { // argument formatted with newlines, do not append on same line logMsg.append(LINE_SEPARATOR); } logMsg.append(argString); } } logMsg.append(LINE_SEPARATOR); return logMsg.toString(); } /*------------------------* * Static utility methods * *------------------------*/ /** * Logs an error. * * @param msg * A indicative message for the error. */ public static void error(String msg) { _log(msg, null, ERROR); } /** * Logs an error. * * @param msg * A indicative message for the error. * @param arg * An argument related to the error. In case arg is an * instance of java.lang.Throwable, the message and stack * trace of the argument will be logged. */ public static void error(String msg, Object arg) { _log(msg, arg, ERROR); } /** * Logs a warning. * * @param msg * A indicative message for the warning. */ public static void warning(String msg) { _log(msg, null, WARNING); } /** * Logs a warning. * * @param msg * A indicative message for the warning. * @param arg * An argument related to the warning. In case arg is an * instance of java.lang.Throwable, the message and stack * trace of the argument will be logged. */ public static void warning(String msg, Object arg) { _log(msg, arg, WARNING); } /** * Logs a message. * * @param msg * A indicative message for the message. */ public static void log(String msg) { _log(msg, null, STATUS); } /** * Logs a message. * * @param msg * A indicative message for the message. * @param arg * An argument related to the message. In case arg is an * instance of java.lang.Throwable, the message and stack * trace of the argument will be logged. */ public static void log(String msg, Object arg) { _log(msg, arg, STATUS); } /** * Logs a trace message. * * @param msg * A indicative message for the trace message. */ public static void trace(String msg) { _log(msg, null, TRACE); } /** * Logs a trace message. * * @param msg * A indicative message for the trace message. * @param arg * An argument related to the trace message. In case arg is * an instance of java.lang.Throwable, the message and * stack trace of the argument will be logged. */ public static void trace(String msg, Object arg) { _log(msg, arg, TRACE); } /** * Logs a message on the specified level. * * @param msg * A indicative message for the trace message. * @param arg * An argument related to the trace message. In case arg is * an instance of java.lang.Throwable, the message and * stack trace of the argument will be logged. * @param level * One of the constants ERROR, WARNING, STATUS, TRACE, or ALL. * @see #ERROR * @see #WARNING * @see #STATUS * @see #TRACE * @see #ALL */ protected static void _log(String msg, Object arg, int level) { ThreadLog threadLog = _getThreadLog(); if (threadLog != null) { threadLog.doLog(msg, arg, level); } } } </source>

Transition Detector

   <source lang="java">
 

public class TransitionDetectorMain extends Object {

 private static Thread startTrueWaiter(final TransitionDetector td,
     String name) {
   Runnable r = new Runnable() {
     public void run() {
       try {
         while (true) {
           print("about to wait for false-to-"
               + "true transition, td=" + td);
           td.waitForFalseToTrueTransition();
           print("just noticed for false-to-"
               + "true transition, td=" + td);
         }
       } catch (InterruptedException ix) {
         return;
       }
     }
   };
   Thread t = new Thread(r, name);
   t.start();
   return t;
 }
 private static Thread startFalseWaiter(final TransitionDetector td,
     String name) {
   Runnable r = new Runnable() {
     public void run() {
       try {
         while (true) {
           print("about to wait for true-to-"
               + "false transition, td=" + td);
           td.waitForTrueToFalseTransition();
           print("just noticed for true-to-"
               + "false transition, td=" + td);
         }
       } catch (InterruptedException ix) {
         return;
       }
     }
   };
   Thread t = new Thread(r, name);
   t.start();
   return t;
 }
 private static void print(String msg) {
   String name = Thread.currentThread().getName();
   System.err.println(name + ": " + msg);
 }
 public static void main(String[] args) {
   try {
     TransitionDetector td = new TransitionDetector(false);
     Thread threadA = startTrueWaiter(td, "threadA");
     Thread threadB = startFalseWaiter(td, "threadB");
     Thread.sleep(200);
     print("td=" + td + ", about to set to "false"");
     td.setValue(false);
     Thread.sleep(200);
     print("td=" + td + ", about to set to "true"");
     td.setValue(true);
     Thread.sleep(200);
     print("td=" + td + ", about to pulse value");
     td.pulseValue();
     Thread.sleep(200);
     threadA.interrupt();
     threadB.interrupt();
   } catch (InterruptedException x) {
     x.printStackTrace();
   }
 }

} class TransitionDetector extends Object {

 private boolean value;
 private Object valueLock;
 private Object falseToTrueLock;
 private Object trueToFalseLock;
 public TransitionDetector(boolean initialValue) {
   value = initialValue;
   valueLock = new Object();
   falseToTrueLock = new Object();
   trueToFalseLock = new Object();
 }
 public void setValue(boolean newValue) {
   synchronized (valueLock) {
     if (newValue != value) {
       value = newValue;
       if (value) {
         notifyFalseToTrueWaiters();
       } else {
         notifyTrueToFalseWaiters();
       }
     }
   }
 }
 public void pulseValue() {
   // Sync on valueLock to be sure that no other threads
   // get into setValue() between these two setValue()
   // calls.
   synchronized (valueLock) {
     setValue(!value);
     setValue(!value);
   }
 }
 public boolean isTrue() {
   synchronized (valueLock) {
     return value;
   }
 }
 public void waitForFalseToTrueTransition() throws InterruptedException {
   synchronized (falseToTrueLock) {
     falseToTrueLock.wait();
   }
 }
 private void notifyFalseToTrueWaiters() {
   synchronized (falseToTrueLock) {
     falseToTrueLock.notifyAll();
   }
 }
 public void waitForTrueToFalseTransition() throws InterruptedException {
   synchronized (trueToFalseLock) {
     trueToFalseLock.wait();
   }
 }
 private void notifyTrueToFalseWaiters() {
   synchronized (trueToFalseLock) {
     trueToFalseLock.notifyAll();
   }
 }
 public String toString() {
   return String.valueOf(isTrue());
 }

}



 </source>
   
  
 
  



View current Threads in a table

   <source lang="java">
 

import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; public class ThreadViewer extends JPanel {

 private ThreadViewerTableModel tableModel = new ThreadViewerTableModel();
 public ThreadViewer() {
   JTable table = new JTable(tableModel);
   table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
   TableColumnModel colModel = table.getColumnModel();
   int numColumns = colModel.getColumnCount();
   for (int i = 0; i < numColumns - 1; i++) {
     TableColumn col = colModel.getColumn(i);
     col.sizeWidthToFit();
     col.setPreferredWidth(col.getWidth() + 5);
     col.setMaxWidth(col.getWidth() + 5);
   }
   JScrollPane sp = new JScrollPane(table);
   setLayout(new BorderLayout());
   add(sp, BorderLayout.CENTER);
 }
 public void dispose() {
   tableModel.stopRequest();
 }
 protected void finalize() throws Throwable {
   dispose();
 }
 public static void main(String[] args) {
   JFrame f = new JFrame(); 
   ThreadViewer viewer = new ThreadViewer();
   f.setContentPane(viewer);
   f.setSize(500, 300);
   f.setVisible(true);
     
   f.setDefaultCloseOperation(1);
   // Keep the main thread from exiting by blocking
   // on wait() for a notification that never comes.
   Object lock = new Object();
   synchronized (lock) {
     try {
       lock.wait();
     } catch (InterruptedException x) {
     }
   }
 }

} class ThreadViewerTableModel extends AbstractTableModel {

 private Object dataLock;
 private int rowCount;
 private Object[][] cellData;
 private Object[][] pendingCellData;
 private final int columnCount;
 private final String[] columnName;
 private final Class[] columnClass;
 private Thread internalThread;
 private volatile boolean noStopRequested;
 public ThreadViewerTableModel() {
   rowCount = 0;
   cellData = new Object[0][0];
   String[] names = { "Priority", "Alive", "Daemon", "Interrupted",
       "ThreadGroup", "Thread Name" };
   columnName = names;
   Class[] classes = { Integer.class, Boolean.class, Boolean.class,
       Boolean.class, String.class, String.class };
   columnClass = classes;
   columnCount = columnName.length;
   dataLock = new Object();
   noStopRequested = true;
   Runnable r = new Runnable() {
     public void run() {
       try {
         runWork();
       } catch (Exception x) {
         // in case ANY exception slips through
         x.printStackTrace();
       }
     }
   };
   internalThread = new Thread(r, "ThreadViewer");
   internalThread.setPriority(Thread.MAX_PRIORITY - 2);
   internalThread.setDaemon(true);
   internalThread.start();
 }
 private void runWork() {
   Runnable transferPending = new Runnable() {
     public void run() {
       transferPendingCellData();
       fireTableDataChanged();
     }
   };
   while (noStopRequested) {
     try {
       createPendingCellData();
       SwingUtilities.invokeAndWait(transferPending);
       Thread.sleep(5000);
     } catch (InvocationTargetException tx) {
       tx.printStackTrace();
       stopRequest();
     } catch (InterruptedException x) {
       Thread.currentThread().interrupt();
     }
   }
 }
 public void stopRequest() {
   noStopRequested = false;
   internalThread.interrupt();
 }
 public boolean isAlive() {
   return internalThread.isAlive();
 }
 private void createPendingCellData() {
   Thread[] thread = findAllThreads();
   Object[][] cell = new Object[thread.length][columnCount];
   for (int i = 0; i < thread.length; i++) {
     Thread t = thread[i];
     Object[] rowCell = cell[i];
     rowCell[0] = new Integer(t.getPriority());
     rowCell[1] = new Boolean(t.isAlive());
     rowCell[2] = new Boolean(t.isDaemon());
     rowCell[3] = new Boolean(t.isInterrupted());
     rowCell[4] = t.getThreadGroup().getName();
     rowCell[5] = t.getName();
   }
   synchronized (dataLock) {
     pendingCellData = cell;
   }
 }
 private void transferPendingCellData() {
   synchronized (dataLock) {
     cellData = pendingCellData;
     rowCount = cellData.length;
   }
 }
 public int getRowCount() {
   return rowCount;
 }
 public Object getValueAt(int row, int col) {
   return cellData[row][col];
 }
 public int getColumnCount() {
   return columnCount;
 }
 public Class getColumnClass(int columnIdx) {
   return columnClass[columnIdx];
 }
 public String getColumnName(int columnIdx) {
   return columnName[columnIdx];
 }
 public static Thread[] findAllThreads() {
   ThreadGroup group = Thread.currentThread().getThreadGroup();
   ThreadGroup topGroup = group;
   while (group != null) {
     topGroup = group;
     group = group.getParent();
   }
   int estimatedSize = topGroup.activeCount() * 2;
   Thread[] slackList = new Thread[estimatedSize];
   int actualSize = topGroup.enumerate(slackList);
   Thread[] list = new Thread[actualSize];
   System.arraycopy(slackList, 0, list, 0, actualSize);
   return list;
 }

}


 </source>