Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Java 9 Concurrency Cookbook, Second Edition

You're reading from   Java 9 Concurrency Cookbook, Second Edition Build highly scalable, robust, and concurrent applications

Arrow left icon
Product type Paperback
Published in Apr 2017
Publisher Packt
ISBN-13 9781787124417
Length 594 pages
Edition 2nd Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Javier Fernández González Javier Fernández González
Author Profile Icon Javier Fernández González
Javier Fernández González
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Thread Management 2. Basic Thread Synchronization FREE CHAPTER 3. Thread Synchronization Utilities 4. Thread Executors 5. Fork/Join Framework 6. Parallel and Reactive Streams 7. Concurrent Collections 8. Customizing Concurrency Classes 9. Testing Concurrent Applications 10. Additional Information 11. Concurrent Programming Design

Grouping threads and processing uncontrolled exceptions in a group of threads

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.

Getting ready

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.

How to do it...

Follow these steps to implement the example:

  1. First, extend the 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);
}
  1. Override the 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();
}
  1. Create a class called Task and specify that it implements the Runnable interface:
        public class Task implements Runnable {
  1. Implement the 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;
}
}
}
  1. Now, implement the main class of the example by creating a class called Main and implement the main() method:
        public class Main { 
public static void main(String[] args) {
  1. First, calculate the number of threads you are going to launch. We use the 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();
  1. Create an object of the MyThreadGroup class:
        MyThreadGroup threadGroup=new MyThreadGroup("MyThreadGroup");
  1. Create an object of the Task class:
        Task task=new Task();
  1. Create the calculated number of Thread objects with this Task class and start them:
        for (int i = 0; i < numberOfThreads; i++) { 
Thread t = new Thread(threadGroup, task);
t.start();
}
  1. Then, write information about 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();
  1. Finally, write the status of the threads that form the group:
            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());
}
}
}
  1. Run the example and see the results.

How it works...

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.

See also

  • The Processing uncontrolled exceptions in a thread recipe
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime