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.

The threads and thread groups of a Swing application

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);
    }
}

Get Java Examples in a Nutshell, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.