4.3 Threads and Thread Groups
Every Java Thread
belongs to some ThreadGroup and may be constrained
and controlled through the methods of that
ThreadGroup. Similarly, every
ThreadGroup is itself contained in some parent
ThreadGroup. Thus, there is a hierarchy of thread
groups and the threads they contain. Example 4-3
shows a ThreadLister class, with a public
listAllThreads( ) method that displays this
hierarchy by listing all threads and thread groups currently running
on the Java interpreter. This method displays the name and priority
of each thread, as well as other information about threads and thread
groups. The example defines a main( ) method that
creates a simple Swing user interface and uses it to display a
listing of its own threads. Figure 4-1 shows such a
listing.
Figure 4-1. The threads and thread groups of a Swing application

The
listAllThreads( ) method uses the static
Thread method currentThread( )
to obtain the current thread and then calls getThreadGroup(
) to find the thread group of that thread. The method then
uses the ThreadGroup.getParent( ) method to move
up through the thread-group hierarchy until it finds the root thread
group, the thread group that contains all other threads and thread
groups.Now
listAllThreads( ) calls the private
ThreadLister.printGroupInfo( ) method to display
the contents of the root thread group and then recursively display
the contents of all the thread groups it contains.
printGroupInfo( ), and the
printThreadInfo( ) method it calls, use various
Thread and ThreadGroup methods
to obtain information about the threads and their groups. Note that
the isDaemon( ) method returns, regardless of
whether a thread is a daemon thread. Daemon threads are background
threads that are not expected to exit. The Java interpreter exits
when all nondaemon threads have quit.The
ThreadLister class has a main(
) method, so it can be run as a standalone program. It is
more interesting, of course, to invoke the listAllThreads(
) method from within another program; it can also help you
to diagnose problems you are having with threads.
Example 4-3. ThreadLister.java
package je3.thread;
import java.io.*;
import java.awt.*; // AWT classes for the demo program
import javax.swing.*; // Swing GUI classes for the demo
/**
* This class contains a useful static method for listing all threads
* and threadgroups in the VM. It also has a simple main( ) method so it
* can be run as a standalone program.
**/
public class ThreadLister {
/** Display information about a thread. */
private static void printThreadInfo(PrintWriter out, Thread t,
String indent) {
if (t == null) return;
out.println(indent + "Thread: " + t.getName( ) +
" Priority: " + t.getPriority( ) +
(t.isDaemon( )?" Daemon":") +
(t.isAlive( )?":" Not Alive"));
}
/** Display info about a thread group and its threads and groups */
private static void printGroupInfo(PrintWriter out, ThreadGroup g,
String indent) {
if (g == null) return;
int num_threads = g.activeCount( );
int num_groups = g.activeGroupCount( );
Thread[ ] threads = new Thread[num_threads];
ThreadGroup[ ] groups = new ThreadGroup[num_groups];
g.enumerate(threads, false);
g.enumerate(groups, false);
out.println(indent + "Thread Group: " + g.getName( ) +
" Max Priority: " + g.getMaxPriority( ) +
(g.isDaemon( )?" Daemon":"));
for(int i = 0; i < num_threads; i++)
printThreadInfo(out, threads[i], indent + " ");
for(int i = 0; i < num_groups; i++)
printGroupInfo(out, groups[i], indent + " ");
}
/** Find the root thread group and list it recursively */
public static void listAllThreads(PrintWriter out) {
ThreadGroup current_thread_group;
ThreadGroup root_thread_group;
ThreadGroup parent;
// Get the current thread group
current_thread_group = Thread.currentThread( ).getThreadGroup( );
// Now go find the root thread group
root_thread_group = current_thread_group;
parent = root_thread_group.getParent( );
while(parent != null) {
root_thread_group = parent;
parent = parent.getParent( );
}
// And list it, recursively
printGroupInfo(out, root_thread_group, ");
}
/**
*The main( )method creates a simple graphical user interface to display
*the threads in.This allows us to see the "event dispatch thread" used
* by AWT and Swing.
**/
public static void main(String[ ] args) {
// Create a simple Swing GUI
JFrame frame = new JFrame("ThreadLister Demo");
JTextArea textarea = new JTextArea( );
frame.getContentPane( ).add(new JScrollPane(textarea),
BorderLayout.CENTER);
frame.setSize(500, 400);
frame.setVisible(true);
// Get the threadlisting as a string using a StringWriter stream
StringWriter sout = new StringWriter( ); // To capture the listing
PrintWriter out = new PrintWriter(sout);
ThreadLister.listAllThreads(out); // List threads to stream
out.close( );
String threadListing = sout.toString( ); // Get listing as a string
// Finally, display the thread listing in the GUI
textarea.setText(threadListing);
}
}