-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating

Java 9 Concurrency Cookbook, Second Edition
By :

An interesting functionality offered by the concurrency API of Java is the ability to group threads. This allows us to treat the threads of a group as a single unit and provide access to the thread objects that belong to a group in order to do an operation with them. For example, you have some threads doing the same task and you want to control them. You can, for example, interrupt all the threads of the group with a single call.
Java provides the ThreadGroup
class to work with a groups of threads. A ThreadGroup
object can be formed by thread objects and another ThreadGroup
object, generating a tree structure of threads.
In the Controlling the interruption of a thread recipe, you learned how to use a generic method to process all the uncaught exceptions that are thrown in a thread object. In the Processing uncontrolled exceptions in a thread recipe, we wrote a handler to process the uncaught exceptions thrown by a thread. We can use a similar mechanism to process the uncaught exceptions thrown by a thread or a group of threads.
In this recipe, we will learn to work with ThreadGroup
objects and how to implement and set the handler that would process uncaught exceptions in a group of threads. We'll do this using an example.
The example for this recipe has been implemented using the Eclipse IDE. If you use Eclipse or a different IDE, such as NetBeans, open it and create a new Java project.
Follow these steps to implement the example:
ThreadGroup
class by creating a class called MyThreadGroup
that would be extended from ThreadGroup
. You have to declare a constructor with one parameter because the ThreadGroup
class doesn't have a constructor without it. Extend the ThreadGroup
class to override the uncaughtException()
method in order to process the exceptions thrown by the threads of the group:public class MyThreadGroup extends ThreadGroup { public MyThreadGroup(String name) { super(name); }
uncaughtException()
method. This method is called when an exception is thrown in one of the threads of the ThreadGroup
class. In this case, the method will write information about the exception and the thread that throws it; it will present this information in the console. Also, note that this method will interrupt the rest of the threads in the ThreadGroup
class:@Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("The thread %s has thrown an Exception\n", t.getId()); e.printStackTrace(System.out); System.out.printf("Terminating the rest of the Threads\n"); interrupt(); }
Task
and specify that it implements the Runnable
interface:public class Task implements Runnable {
run()
method. In this case, we will provoke an AritmethicException
exception. For this, we will divide 1,000 with random numbers until the random generator generates zero to throw the exception:@Override public void run() { int result; Random random=new Random(Thread.currentThread().getId()); while (true) { result=1000/((int)(random.nextDouble()*1000000000)); if (Thread.currentThread().isInterrupted()) { System.out.printf("%d : Interrupted\n", Thread.currentThread().getId()); return; } } }
Main
and implement the main()
method:public class Main { public static void main(String[] args) {
availableProcessors()
method of the Runtime
class (we obtain the runtime object associated with the current Java application with the static method, called getRuntime()
, of that class). This method returns the number of processors available to the JVM, which is normally equal to the number of cores of the computer that run the application:int numberOfThreads = 2 * Runtime.getRuntime() .availableProcessors();
MyThreadGroup
class:MyThreadGroup threadGroup=new MyThreadGroup("MyThreadGroup");
Task
class:Task task=new Task();
Thread
objects with this Task
class and start them:for (int i = 0; i < numberOfThreads; i++) { Thread t = new Thread(threadGroup, task); t.start(); }
ThreadGroup
in the console:System.out.printf("Number of Threads: %d\n", threadGroup.activeCount()); System.out.printf("Information about the Thread Group\n"); threadGroup.list();
Thread[] threads = new Thread[threadGroup.activeCount()]; threadGroup.enumerate(threads); for (int i = 0; i < threadGroup.activeCount(); i++) { System.out.printf("Thread %s: %s\n", threads[i].getName(), threads[i].getState()); } } }
In the following screenshot, you can see the output of the list()
method of the ThreadGroup
class and the output generated when we write the status of each Thread
object:
The ThreadGroup
class stores thread objects and other ThreadGroup
objects associated with it so it can access all of their information (status, for example) and perform operations over all its members (interrupt, for example).
Check out how one of the thread objects threw the exception that interrupted the other objects:
When an uncaught exception is thrown in a Thread
object, the JVM looks for three possible handlers for this exception.
First, it looks for the uncaught exception handler of the thread, as explained in the Processing uncontrolled exceptions in a thread recipe. If this handler doesn't exist, then the JVM looks for the uncaught exception handler of the ThreadGroup
class of the thread, as learned in this recipe. If this method doesn't exist, the JVM looks for the default uncaught exception handler, as explained in the Processing uncontrolled exceptions in a thread recipe.
If none of the handlers exists, the JVM writes the stack trace of the exception in the console and ends the execution of the thread that had thrown the exception.