Monday, June 6, 2016

Java : Usage of ThreadGroup with Example

All of you from java family must be aware about the packaging concept. Why we create a package in java? We create a package in java just for the categorization of the classes of similar types in separate groups. You might be thinking why I started the package concept under the ThreadGroup. Actually, if I talk in one line, ThreadGroup is nothing but the categorization of the similar threads in separate groups. I hope I am clear.

For better understanding let's take the following points as an example:

1) System Threads are the group of threads which system takes care of. like: Main thread is under the category of System Threads. So, main is a sub-group of System Threads and System Threads can be named as System Thread Group.

2) Suppose I created Thread1, Thread2 and Thread3 in the main method then These can be put in the Sub-Group1 which can be considered as a ThreadGroup. Although, there might be multiple groups of threads like Sub-Group1 hence all will be the ThreadGroups of different kinds. One group of Threads might be given the task of contacting to database. Another group of Threads might be given the task of calculating the business logic, one another group of Threads might be given the task of showing the result on UI. Hence, all of these will be under such Groups which will be called ThreadGroups. The main point to note here is that Main would be the parent ThreadGroup of these sub-groups.

Now, lets discuss about the constructors of ThreadGroup so that we can come to know how to create ThreadGroup in our java multi-threading application:

public static void main (String [] args){
   ThreadGroup group1 = new ThreadGroup ("Group1");         // constructor1
   ThreadGroup group2 = new ThreadGroup (group1, "Group2"); // constructor2
}

In the constructor1, a ThreadGroup is created by just giving the ThreadGroup name.
In the constructor2, a ThreadGroup is created by giving the ThreadGroup name plus the parent name of this ThreadGroup as the first argument.

In the constructor1, it will be considered that the parent of this ThreadGroup is main itself(if it is defined in main or any other context where it would be defined).


How to destory ThreadGroup created in the application:

Once you no longer need the ThreadGroup objects, you can call ThreadGroup's destroy() method like below:

group1.destroy();      // group1 is the reference of the ThreadGroup

Here is some twist in the story: If the top ThreadGroup reference calls destroy() then all the sub groups will be available for the garbage collection because if the parent is destroyed the child ThreadGroups will automatically be nullify and would be available for the garbage collection.Otherwise, destroy() throws an IllegalThreadStateException object.


Let us demonstrate the above story by the below example:

class ThreadGroupDemo
{
   public static void main (String [] args)
   {
      ThreadGroup group1 = new ThreadGroup ("sub-group1");
      Thread t1 = new Thread (group1, "thread 1");
      Thread t2 = new Thread (group1, "thread 2");
      Thread t3 = new Thread (group1, "thread 3");
      group1 = new ThreadGroup (group1,"sub-group2");
      Thread t4 = new Thread (group1, "my fourth thread");
      group1 = Thread.currentThread ().getThreadGroup ();
      int groupCount = group1.activeGroupCount ();
      System.out.println ("Active thread groups in " + group1.getName () + " thread group: " + groupCount);
      group1.list ();
   }
}

Output would be like:

Active thread groups in main thread group: 2
java.lang.ThreadGroup[name=main,maxpri=10]
    Thread[main,5,main]
    java.lang.ThreadGroup[name=subgroup 1,maxpri=10]
        java.lang.ThreadGroup[name=subgroup 2,maxpri=10]


In the example code above, sub-group1 is the sub ThreadGroups of main ThreadGroup. sub-group2 is the sub ThreadGroup of sub-group1.

Now let's talk something about the Priority of ThreadGroups:

Suppose a ThreadGroup is having five Threads and one of the thread can attain a maximum priority from these five threads, then that priority will be the ThreadGroup's maximum priority. Use ThreadGroup's void setMaxPriority(int priority) method to subsequently set the maximum priority.Any threads that you add to the group after setting its maximum priority cannot have a priority that exceeds the maximum. It means if the max priority of the ThreadGroup is set to 6 then any of the threads of this group can not have a priority 7. So, any thread with a higher priority automatically lowers when it joins the thread group. Although, vise-versa is not true i.e. However, if you use setMaxPriority(int priority) to lower a group's maximum priority, all threads added to the group prior to that method call keep their original priorities. For example, if you add a priority 8 thread to a maximum priority 9 group, and then lower that group's maximum priority to 7, the priority 8 thread remains at priority 8.

Let's have an example to demonstrate it:

class MaxPriorityDemo
{
   public static void main (String [] args)
   {
      ThreadGroup group1 = new ThreadGroup ("A Group");
      System.out.println ("group1 maximum priority = " + group1.getMaxPriority ());
      Thread thread1 = new Thread (group1, "X Thread");
      System.out.println ("thread1 priority = " + thread1.getPriority ());
      thread1.setPriority (Thread.NORM_PRIORITY + 1);
      System.out.println ("thread1 priority after setPriority() = " + thread1.getPriority ());
      group1.setMaxPriority (Thread.NORM_PRIORITY - 1);
      System.out.println ("group1 maximum priority after setMaxPriority() = " + group1.getMaxPriority ());
      System.out.println ("thread1 priority after setMaxPriority() = " +thread1.getPriority ());
      Thread thread2 = new Thread (group1, "Y Thread");
      System.out.println ("thread2 priority = " + thread2.getPriority ());
      thread2.setPriority (Thread.NORM_PRIORITY);
      System.out.println ("thread2 priority after setPriority() = " + thread2.getPriority ());
   }
}

Output would be like that:

group1 maximum priority = 10
thread1 priority = 5
thread1 priority after setPriority() = 6
group1 maximum priority after setMaxPriority() = 4
thread1 priority after setMaxPriority() = 6
thread2 priority = 4
thread2 priority after setPriority() = 4


Now, let's talk about the ThreadGroup Interuption:

In addition to using ThreadGroups to limit thread priority, you can accomplish other tasks by calling various ThreadGroup methods that apply to each group's thread. Methods include void suspend(), void resume(), void stop(), and void interrupt(). Because Sun Microsystems has deprecated the first three methods (they are unsafe), we examine only interrupt().

ThreadGroup's has an interrupt() method that allows a thread to interrupt a specific ThreadGroup's all threads and subgroups. Main thread creates multiple threads and each perform a unit of work. Because all threads must complete their work before any thread can examine the results, each thread waits after completing its work. The main thread monitors the working state. When all other threads are waiting, the main thread calls interrupt() to interrupt the other threads' waits. Then those threads can examine and process the results.




No comments:

Post a Comment