ThreadGroup in Java with Examples

A thread group represents a set of threads. In addition, a thread group may also contain other thread groups. Thread groups form a tree in which each thread group has a parent except for the initial thread group.

How ThreadGroup Works In Java?

A thread group is a collection of several related threads. A thread pool allows developers to process multiple Java threads simultaneously and is available in the java.lang package.Internally, a thread group can be thought of as a tree in which every thread has a parent, except for a parent thread that is not assigned to it.

It should be noted that a thread belonging to one particular thread group is able to obtain information about the same thread group it belongs to, but has no information on its parent or any other thread group.

Example code:

public class Techvidvan Test implements Runnable{
public void run()
{
       }
  public static void main(String[] args) {
      ThreadGroupTest threadGroupTest = new ThreadGroupTest();
      ThreadGroup threadGroup = new ThreadGroup("Parent Thread Group");
       Thread t1 = new Thread(threadGroup, threadGroupTest,"T1");
      t1.start();
      Thread t2 = new Thread(threadGroup, threadGroupTest,"T2");
      t2.start();
      Thread t3 = new Thread(threadGroup, threadGroupTest,"T3");
      t3.start();
System.out.println("Thread Group Name: "+threadGroup.getName());
      threadGroup.list();
  }
}

Output:
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2

Life Cycle Of Thread:

In Java, a thread always exists in any of the following states. These states are:

New
Active
Blocked / Waiting
Timed waiting
Ended

import java.lang.*;
class NewThread extends Thread
{
    NewThread(String threadname, ThreadGroup tgob)
    {
        super(tgob, threadname);
        start();
    }
public void run()
    {

        for (int i = 0; i < 1000; i++)
        {
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException ex)
            {
                System.out.println("Exception encounterted");
            }
        }
        System.out.println(Thread.currentThread().getName() +
            " finished executing");
    }
}
public class ThreadGroupDemo
{
    public static void main(String arg[]) throws InterruptedException
    {
        // creating the thread group
        ThreadGroup gfg = new ThreadGroup("gfg");

        ThreadGroup gfg_child = new ThreadGroup(gfg, "child");

        NewThread t1 = new NewThread("one", gfg);
        System.out.println("Starting one");
        NewThread t2 = new NewThread("two", gfg);
        System.out.println("Starting two");

        // checking the number of active thread
        System.out.println("number of active thread group: "
                        + gfg.activeGroupCount());
    }
}

Output:
The state of thread t1 after spawning it – NEW
The state of thread t1 after invoking the method start() on it – RUNNABLE
The state of thread t2 after spawning it – NEW
the state of thread t2 after calling the method start() on it – RUNNABLE
The state of thread t1 while it invoked the method join() on thread t2 –TIMED_WAITING
The state of thread t2 after invoking the method sleep() on it – TIMED_WAITING
The state of thread t2 when it has completed its execution – TERMINATED

void destroy() Destroys a thread groupint enumerate(Thread[] list) Copies each thread in the thread group to the specified array int enumerate(ThreadGroup[] list) Copies each active subgroup in the thread group to the specified array int enumerate.

import java.lang.*;
class NewThread extends Thread
{
    NewThread(String threadname, ThreadGroup tgob)
    {
        super(tgob, threadname);
        start();
    }
public void run()
    {

        for (int i = 0; i < 10; i++)
        {
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException ex)
            {
                System.out.println("Exception encounterted");
            }
        }
    }
}
public class ThreadGroupDemo
{
    public static void main(String arg[]) throws InterruptedException,
        SecurityException
    {
        ThreadGroup gfg = new ThreadGroup("Parent thread");

        ThreadGroup gfg_child = new ThreadGroup(gfg, "child thread");

        NewThread t1 = new NewThread("one", gfg);
        System.out.println("Starting one");
        NewThread t2 = new NewThread("two", gfg);
        System.out.println("Starting two");
        t1.join();
        t2.join();
        gfg_child.destroy();
        System.out.println(gfg_child.getName() + " destroyed");
        gfg.destroy();
        System.out.println(gfg.getName() + " destroyed");
    }
}

Output:
Starting the first
Starting the second
the first thread has finished executing
the second thread has finished executing
the child group is destroyed.
the parent group is destroyed.

If recursion is true, calls this operation recursively int enumerate(threadgroup list[], boolean recursion) Copies each active subgroup in the thread group to the specified array.

If recursion is true, calls this operation recursively int getMaximumPriority() Returns the maximum priority of the thread group getName() Returns the name of the thread group groupThreadGroup getParent() Returns the parent of the thread group.

import java.lang.*;
class NewThread extends Thread
{
    NewThread(String threadname, ThreadGroup tgob)
    {
        super(tgob, threadname);
        start();
    }
public void run()
    {

        for (int i = 0; i < 10; i++)
        {
            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException ex)
            {
            System.out.println("Thread " + Thread.currentThread().getName()
                                + " interrupted");
            }
        }
        System.out.println(Thread.currentThread().getName() +
            " finished executing");
    }
}
public class ThreadGroupDemo
{
    public static void main(String arg[]) throws InterruptedException,
        SecurityException
    {
        ThreadGroup gfg = new ThreadGroup("Parent thread");
        ThreadGroup gfg_child = new ThreadGroup(gfg, "child thread");

        NewThread t1 = new NewThread("one", gfg);
        System.out.println("Starting " + t1.getName());
        NewThread t2 = new NewThread("two", gfg);
        System.out.println("Starting " + t2.getName());
        gfg.interrupt();
    }
}

Output:
Starting hello thread…
Starting goodbye thread…
Hello
Hello
Hello
Hello
Hello
Hello
Goodbye
Goodbye
Goodbye
Goodbye
Goodbye
…….

Need For Java Thread Group:

Java thread pooling allows developers to process multiple Java threads simultaneously, which is available in Java. lang package. In theory, a thread group is a tree in which every thread has a parent, except for a parent thread that is not assigned to it. All Java threads are members of the thread pool. Thread groups are a mechanism for accumulating multiple threads in an object and manipulating them at once, instead of individually.

Advantages:

  • Logical organization of your threads (for diagnostic purposes).
  • You can break() all threads in a group. (Abort is perfectly fine, unlike suspend(), continue() and stop()).
  • You can set the maximum priority of threads in a group. (not sure how widely useful this is, but there you have it).
  • Sets the ThreadGroup as a daemon. (So ​​any new threads added to it will be daemon threads).
  • It allows you to override its uncaughtExceptionHandler so that if one of the threads in the group throws an exception, you’ll have a callback to handle it.

Disadvantages:

Complicatity: It’s a matter of thinking about how different threads are going to interact and coordinate with one another, which is what adds complexity to your code. If this is the case, it may be hard to decipher and debug your code

Resource overhead: System resources, e.g. memory or processing power, are needed to create and manage threads. This, in particular when you build a lot of threads, can have an effect on your program’s performance.

Race condition: when multiple threads attempt to access and modify a common set of data at the same time, race conditions can occur if it is not clear what their final state will be. To debug this could be hard to do, and it may result in unpredictable behavior within your program. A deadlock occurs when, in order to release the resource, two or more threads wait on one another and are prevented from leaving an infinite loop.

Scheduling: You don’t guarantee the order of threads that are scheduled, which can cause unexpected behavior in your program.

Conclusion

A set of threads is represented by a group of threads. A second group of fibers may also be included in the fiber group. A thread group forms a tree in which each thread group has a parent group except the initial thread group.