0% found this document useful (0 votes)
2 views

Multithreading in Java2_Life cycle of a Thread_27_11_2023(2)

The document outlines the life cycle of a thread in Java, detailing its various states: New, Active, Blocked/Waiting, Timed Waiting, and Terminated. It explains how threads transition between these states based on actions like invoking start(), join(), and sleep(), and provides examples of how to create threads using both the Thread class and the Runnable interface. Additionally, it discusses thread scheduling and the methods available in the Thread class for managing thread behavior.

Uploaded by

tijjanifatima01
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Multithreading in Java2_Life cycle of a Thread_27_11_2023(2)

The document outlines the life cycle of a thread in Java, detailing its various states: New, Active, Blocked/Waiting, Timed Waiting, and Terminated. It explains how threads transition between these states based on actions like invoking start(), join(), and sleep(), and provides examples of how to create threads using both the Thread class and the Runnable interface. Additionally, it discusses thread scheduling and the methods available in the Thread class for managing thread behavior.

Uploaded by

tijjanifatima01
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 94

Life cycle of a Thread (Thread States)

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

1. New
2. Active
3. Blocked / Waiting
4. Timed Waiting
5. Terminated

Explanation of Different Thread States


New: Whenever a new thread is created, it is always in the new state. For a thread in the
new state, the code has not been run yet and thus has not begun its execution.

Active: When a thread invokes the start() method, it moves from the new state to the
active state. The active state contains two states within it: one is runnable, and the other
is running.

o Runnable: A thread, that is ready to run is then moved to the runnable state. In
the runnable state, the thread may be running or may be ready to run at any given
instant of time. It is the duty of the thread scheduler to provide the thread time to
run, i.e., moving the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each
individual thread. Each and every thread runs for a short span of time and when
that allocated time slice is over, the thread voluntarily gives up the CPU to the other
thread, so that the other threads can also run for their slice of time. Whenever such
a scenario occurs, all those threads that are willing to run, waiting for their turn to
run, lie in the runnable state. In the runnable state, there is a queue where the
threads lie.
o Running: When the thread gets the CPU, it moves from the runnable to the
running state. Generally, the most common change in the state of a thread is from
runnable to running and again back to runnable.

Blocked or Waiting: Whenever a thread is inactive for a span of time (not permanently)
then, either the thread is in the blocked state or is in the waiting state.
1
For example, a thread (let's say its name is A) may want to print some data from the
printer. However, at the same time, the other thread (let's say its name is B) is using the
printer to print some data. Therefore, thread A has to wait for thread B to use the printer.
Thus, thread A is in the blocked state. A thread in the blocked state is unable to perform
any execution and thus never consume any cycle of the Central Processing Unit (CPU).
Hence, we can say that thread A remains idle until the thread scheduler reactivates thread
A, which is in the waiting or blocked state.

When the main thread invokes the join() method then, it is said that the main thread is in
the waiting state. The main thread then waits for the child threads to complete their tasks.
When the child threads complete their job, a notification is sent to the main thread, which
again moves the thread from waiting to the active state.

If there are a lot of threads in the waiting or blocked state, then it is the duty of the thread
scheduler to determine which thread to choose and which one to reject, and the chosen
thread is then given the opportunity to run.

Timed Waiting: Sometimes, waiting for leads to starvation. For example, a thread (its
name is A) has entered the critical section of a code and is not willing to leave that critical
section. In such a scenario, another thread (its name is B) has to wait forever, which leads
to starvation. To avoid such scenario, a timed waiting state is given to thread B. Thus,
thread lies in the waiting state for a specific span of time, and not forever. A real example
of timed waiting is when we invoke the sleep() method on a specific thread. The sleep()
method puts the thread in the timed wait state. After the time runs out, the thread wakes
up and start its execution from when it has left earlier.

Terminated: A thread reaches the termination state because of the following reasons:

o When a thread has finished its job, then it exists or terminates normally.
o Abnormal termination: It occurs when some unusual events such as an
unhandled exception or segmentation fault.

A terminated thread means the thread is no more in the system. In other words, the thread
is dead, and there is no way one can respawn (active after kill) the dead thread.

The following diagram shows the different states involved in the life cycle of a thread.

2
Implementation of Thread States
In Java, one can get the current state of a thread using the Thread.getState() method.
The java.lang.Thread.State class of Java provides the constants ENUM to represent the
state of a thread. These constants are:

1. public static final Thread.State NEW

It represents the first state of a thread that is the NEW state.

1. public static final Thread.State RUNNABLE

It represents the runnable state.It means a thread is waiting in the queue to run.

1. public static final Thread.State BLOCKED

It represents the blocked state. In this state, the thread is waiting to acquire a lock.

1. public static final Thread.State WAITING

It represents the waiting state. A thread will go to this state when it invokes the
Object.wait() method, or Thread.join() method with no timeout. A thread in the waiting
state is waiting for another thread to complete its task.

1. public static final Thread.State TIMED_WAITING

It represents the timed waiting state. The main difference between waiting and timed
waiting is the time constraint. Waiting has no time constraint, whereas timed waiting has
the time constraint. A thread invoking the following method reaches the timed waiting
state.

o sleep
o join with timeout
o wait with timeout
o parkUntil
o parkNanos

1. public static final Thread.State TERMINATED

3
It represents the final state of a thread that is terminated or dead. A terminated thread
means it has completed its execution.

Java Program for Demonstrating Thread States


The following Java program shows some of the states of a thread defined above.

FileName: ThreadState.java

1. // ABC class implements the interface Runnable


2. class ABC implements Runnable
3. {
4. public void run()
5. {
6.
7. // try-catch block
8. try
9. {
10. // moving thread t2 to the state timed waiting
11. Thread.sleep(100);
12. }
13. catch (InterruptedException ie)
14. {
15. ie.printStackTrace();
16. }
17.
18.
19. System.out.println("The state of thread t1 while it invoked the method join() on thread t2 -
"+ ThreadState.t1.getState());
20.
21. // try-catch block
22. try
23. {
24. Thread.sleep(200);
25. }
26. catch (InterruptedException ie)
4
27. {
28. ie.printStackTrace();
29. }
30. }
31. }
32.
33. // ThreadState class implements the interface Runnable
34. public class ThreadState implements Runnable
35. {
36. public static Thread t1;
37. public static ThreadState obj;
38.
39. // main method
40. public static void main(String argvs[])
41. {
42. // creating an object of the class ThreadState
43. obj = new ThreadState();
44. t1 = new Thread(obj);
45.
46. // thread t1 is spawned
47. // The thread t1 is currently in the NEW state.
48. System.out.println("The state of thread t1 after spawning it - " + t1.getState());
49.
50. // invoking the start() method on
51. // the thread t1
52. t1.start();
53.
54. // thread t1 is moved to the Runnable state
55. System.out.println("The state of thread t1 after invoking the method start() on it - " + t1.
getState());
56. }
57.
58. public void run()
59. {

5
60. ABC myObj = new ABC();
61. Thread t2 = new Thread(myObj);
62.
63. // thread t2 is created and is currently in the NEW state.
64. System.out.println("The state of thread t2 after spawning it - "+ t2.getState());
65. t2.start();
66.
67. // thread t2 is moved to the runnable state
68. System.out.println("the state of thread t2 after calling the method start() on it - " + t2.ge
tState());
69.
70. // try-catch block for the smooth flow of the program
71. try
72. {
73. // moving the thread t1 to the state timed waiting
74. Thread.sleep(200);
75. }
76. catch (InterruptedException ie)
77. {
78. ie.printStackTrace();
79. }
80.
81. System.out.println("The state of thread t2 after invoking the method sleep() on it - "+ t2.
getState() );
82.
83. // try-catch block for the smooth flow of the program
84. try
85. {
86. // waiting for thread t2 to complete its execution
87. t2.join();
88. }
89. catch (InterruptedException ie)
90. {
91. ie.printStackTrace();

6
92. }
93. System.out.println("The state of thread t2 when it has completed it's execution - " + t2.g
etState());
94. }
95.
96. }

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 it's execution - TERMINATED

Explanation: Whenever we spawn a new thread, that thread attains the new state. When
the method start() is invoked on a thread, the thread scheduler moves that thread to the
runnable state. Whenever the join() method is invoked on any thread instance, the current
thread executing that statement has to wait for this thread to finish its execution, i.e.,
move that thread to the terminated state. Therefore, before the final print statement is
printed on the console, the program invokes the method join() on thread t2, making the
thread t1 wait while the thread t2 finishes its execution and thus, the thread t2 get to the
terminated or dead state. Thread t1 goes to the waiting state because it is waiting for
thread t2 to finish it's execution as it has invoked the method join() on thread t2.

7
Java Threads | How to create a thread in Java
There are two ways to create a thread:

1. By extending Thread class


2. By implementing Runnable interface.

Thread class:
Thread class provide constructors and methods to create and perform operations on a
thread.Thread class extends Object class and implements Runnable interface.

Commonly used Constructors of Thread class:


o Thread()
o Thread(String name)
o Thread(Runnable r)
o Thread(Runnable r,String name)

Commonly used methods of Thread class:


1. public void run(): is used to perform action for a thread.
2. public void start(): starts the execution of the thread.JVM calls the run() method on the
thread.
3. public void sleep(long miliseconds): Causes the currently executing thread to sleep
(temporarily cease execution) for the specified number of milliseconds.
4. public void join(): waits for a thread to die.
5. public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
6. public int getPriority(): returns the priority of the thread.
7. public int setPriority(int priority): changes the priority of the thread.
8. public String getName(): returns the name of the thread.
9. public void setName(String name): changes the name of the thread.
10. public Thread currentThread(): returns the reference of currently executing thread.
11. public int getId(): returns the id of the thread.

8
12. public Thread.State getState(): returns the state of the thread.
13. public boolean isAlive(): tests if the thread is alive.
14. public void yield(): causes the currently executing thread object to temporarily pause and
allow other threads to execute.
15. public void suspend(): is used to suspend the thread(depricated).
16. public void resume(): is used to resume the suspended thread(depricated).
17. public void stop(): is used to stop the thread(depricated).
18. public boolean isDaemon(): tests if the thread is a daemon thread.
19. public void setDaemon(boolean b): marks the thread as daemon or user thread.
20. public void interrupt(): interrupts the thread.
21. public boolean isInterrupted(): tests if the thread has been interrupted.
22. public static boolean interrupted(): tests if the current thread has been interrupted.

Runnable interface:
The Runnable interface should be implemented by any class whose instances are intended
to be executed by a thread. Runnable interface have only one method named run().

1. public void run(): is used to perform action for a thread.

Starting a thread:
The start() method of Thread class is used to start a newly created thread. It performs
the following tasks:

o A new thread starts(with new callstack).


o The thread moves from New state to the Runnable state.
o When the thread gets a chance to execute, its target run() method will run.

9
1) Java Thread Example by extending Thread class
FileName: Multi.java

1. class Multi extends Thread{


2. public void run(){
3. System.out.println("thread is running...");
4. }
5. public static void main(String args[]){
6. Multi t1=new Multi();
7. t1.start();
8. }
9. }

Output:

thread is running...
2) Java Thread Example by implementing Runnable interface
FileName: Multi3.java

1. class Multi3 implements Runnable{


2. public void run(){
3. System.out.println("thread is running...");
4. }
5.
6. public static void main(String args[]){
7. Multi3 m1=new Multi3();
8. Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
9. t1.start();
10. }
11. }

Output:

thread is running...

10
If you are not extending the Thread class, your class object would not be treated as a
thread object. So you need to explicitly create the Thread class object. We are passing the
object of your class that implements Runnable so that your class run() method may
execute.

3) Using the Thread Class: Thread(String Name)


We can directly use the Thread class to spawn new threads using the constructors defined
above.

FileName: MyThread1.java

1. public class MyThread1


2. {
3. // Main method
4. public static void main(String argvs[])
5. {
6. // creating an object of the Thread class using the constructor Thread(String name)
7. Thread t= new Thread("My first thread");
8.
9. // the start() method moves the thread to the active state
10. t.start();
11. // getting the thread name by invoking the getName() method
12. String str = t.getName();
13. System.out.println(str);
14. }
15. }

Output:

My first thread

4) Using the Thread Class: Thread(Runnable r, String name)


Observe the following program.

11
FileName: MyThread2.java

1. public class MyThread2 implements Runnable


2. {
3. public void run()
4. {
5. System.out.println("Now the thread is running ...");
6. }
7.
8. // main method
9. public static void main(String argvs[])
10. {
11. // creating an object of the class MyThread2
12. Runnable r1 = new MyThread2();
13.
14. // creating an object of the class Thread using Thread(Runnable r, String name)
15. Thread th1 = new Thread(r1, "My new thread");
16.
17. // the start() method moves the thread to the active state
18. th1.start();
19.
20. // getting the thread name by invoking the getName() method
21. String str = th1.getName();
22. System.out.println(str);
23. }
24. }

Output:

My new thread
Now the thread is running ...

12
Thread Scheduler in Java
A component of Java that decides which thread to run or execute and which thread to
wait is called a thread scheduler in Java. In Java, a thread is only chosen by a thread
scheduler if it is in the runnable state. However, if there is more than one thread in the
runnable state, it is up to the thread scheduler to pick one of the threads and ignore the
other ones. There are some criteria that decide which thread will execute first. There are
two factors for scheduling a thread i.e. Priority and Time of arrival.

Priority: Priority of each thread lies between 1 to 10. If a thread has a higher priority, it
means that thread has got a better chance of getting picked up by the thread scheduler.

Time of Arrival: Suppose two threads of the same priority enter the runnable state, then
priority cannot be the factor to pick a thread from these two threads. In such a
case, arrival time of thread is considered by the thread scheduler. A thread that arrived
first gets the preference over the other threads.

Thread Scheduler Algorithms


On the basis of the above-mentioned factors, the scheduling algorithm is followed by a
Java thread scheduler.

First Come First Serve Scheduling:


In this scheduling algorithm, the scheduler picks the threads thar arrive first in the
runnable queue. Observe the following table:

Threads Time of Arrival

t1 0

t2 1

t3 2

t4 3

13
In the above table, we can see that Thread t1 has arrived first, then Thread t2, then t3, and
at last t4, and the order in which the threads will be processed is according to the time of
arrival of threads.

Hence, Thread t1 will be processed first, and Thread t4 will be processed last.

Time-slicing scheduling:
Usually, the First Come First Serve algorithm is non-preemptive, which is bad as it may
lead to infinite blocking (also known as starvation). To avoid that, some time-slices are
provided to the threads so that after some time, the running thread has to give up the
CPU. Thus, the other waiting threads also get time to run their job.

14
In the above diagram, each thread is given a time slice of 2 seconds. Thus, after 2 seconds, the
first thread leaves the CPU, and the CPU is then captured by Thread2. The same process repeats
for the other threads too.

Preemptive-Priority Scheduling:
The name of the scheduling algorithm denotes that the algorithm is related to the priority
of the threads.

Suppose there are multiple threads available in the runnable state. The thread scheduler
picks that thread that has the highest priority. Since the algorithm is also preemptive,
therefore, time slices are also provided to the threads to avoid starvation. Thus, after some
time, even if the highest priority thread has not completed its job, it has to release the
CPU because of preemption.

15
Working of the Java Thread Scheduler

Let's understand the working of the Java thread scheduler. Suppose, there are five threads
that have different arrival times and different priorities. Now, it is the responsibility of the
thread scheduler to decide which thread will get the CPU first.

The thread scheduler selects the thread that has the highest priority, and the thread
begins the execution of the job. If a thread is already in runnable state and another thread
(that has higher priority) reaches in the runnable state, then the current thread is pre-
empted from the processor, and the arrived thread with higher priority gets the CPU time.

When two threads (Thread 2 and Thread 3) having the same priorities and arrival time,
the scheduling will be decided on the basis of FCFS algorithm. Thus, the thread that arrives
first gets the opportunity to execute first.

16
Thread.sleep() in Java with Examples
The Java Thread class provides the two variant of the sleep() method. First one accepts
only an arguments, whereas the other variant accepts two arguments. The method sleep()
is being used to halt the working of a thread for a given amount of time. The time up to
which the thread remains in the sleeping state is known as the sleeping time of the thread.
After the sleeping time is over, the thread starts its execution from where it has left.

The sleep() Method Syntax:


Following are the syntax of the sleep() method.

1. public static void sleep(long mls) throws InterruptedException


2. public static void sleep(long mls, int n) throws InterruptedException

The method sleep() with the one parameter is the native method, and the implementation
of the native method is accomplished in another programming language. The other
methods having the two parameters are not the native method. That is, its
implementation is accomplished in Java. We can access the sleep() methods with the help
of the Thread class, as the signature of the sleep() methods contain the static keyword.
The native, as well as the non-native method, throw a checked Exception. Therefore, either
try-catch block or the throws keyword can work here.

The Thread.sleep() method can be used with any thread. It means any other thread or the
main thread can invoke the sleep() method.

Parameters:
The following are the parameters used in the sleep() method.

mls: The time in milliseconds is represented by the parameter mls. The duration for which
the thread will sleep is given by the method sleep().

n: It shows the additional time up to which the programmer or developer wants the thread
to be in the sleeping state. The range of n is from 0 to 999999.

The method does not return anything.

17
Important Points to Remember About the Sleep() Method
Whenever the Thread.sleep() methods execute, it always halts the execution of the current
thread.

Whenever another thread does interruption while the current thread is already in the sleep
mode, then the InterruptedException is thrown.

If the system that is executing the threads is busy, then the actual sleeping time of the
thread is generally more as compared to the time passed in arguments. However, if the
system executing the sleep() method has less load, then the actual sleeping time of the
thread is almost equal to the time passed in the argument.

Example of the sleep() method in Java : on the custom thread


The following example shows how one can use the sleep() method on the custom thread.

FileName: TestSleepMethod1.java

1. class TestSleepMethod1 extends Thread{


2. public void run(){
3. for(int i=1;i<5;i++){
4. // the thread will sleep for the 500 milli seconds
5. try{Thread.sleep(500);}catch(InterruptedException e){System.out.println(e);}
6. System.out.println(i);
7. }
8. }
9. public static void main(String args[]){
10. TestSleepMethod1 t1=new TestSleepMethod1();
11. TestSleepMethod1 t2=new TestSleepMethod1();
12.
13. t1.start();
14. t2.start();
15. }
16. }

Output:

18
1
1
2
2
3
3
4
4

As you know well that at a time only one thread is executed. If you sleep a thread for the
specified time, the thread scheduler picks up another thread and so on.

Example of the sleep() Method in Java : on the main thread


FileName: TestSleepMethod2.java

1. // important import statements


2. import java.lang.Thread;
3. import java.io.*;
4.
5.
6. public class TestSleepMethod2
7. {
8. // main method
9. public static void main(String argvs[])
10. {
11.
12. try {
13. for (int j = 0; j < 5; j++)
14. {
15.
16. // The main thread sleeps for the 1000 milliseconds, which is 1 sec
17. // whenever the loop runs
18. Thread.sleep(1000);
19.
20. // displaying the value of the variable
21. System.out.println(j);

19
22. }
23. }
24. catch (Exception expn)
25. {
26. // catching the exception
27. System.out.println(expn);
28. }
29. }
30. }

Output:

0
1
2
3
4

Example of the sleep() Method in Java: When the sleeping time


is -ive
The following example throws the exception IllegalArguementException when the time
for sleeping is negative.

FileName: TestSleepMethod3.java

1. // important import statements


2. import java.lang.Thread;
3. import java.io.*;
4.
5. public class TestSleepMethod3
6. {
7. // main method
8. public static void main(String argvs[])
9. {
10. // we can also use throws keyword followed by
11. // exception name for throwing the exception
12. try

20
13. {
14. for (int j = 0; j < 5; j++)
15. {
16.
17. // it throws the exception IllegalArgumentException
18. // as the time is -ive which is -100
19. Thread.sleep(-100);
20.
21. // displaying the variable's value
22. System.out.println(j);
23. }
24. }
25. catch (Exception expn)
26. {
27.
28. // the exception iscaught here
29. System.out.println(expn);
30. }
31. }
32. }

Output:

java.lang.IllegalArgumentException: timeout value is negative

21
Can we start a thread twice
No. After starting a thread, it can never be started again. If you does so,
an IllegalThreadStateException is thrown. In such case, thread will run once but for second
time, it will throw exception.

Let's understand it by the example given below:

1. public class TestThreadTwice1 extends Thread{


2. public void run(){
3. System.out.println("running...");
4. }
5. public static void main(String args[]){
6. TestThreadTwice1 t1=new TestThreadTwice1();
7. t1.start();
8. t1.start();
9. }
10. }

Output:

running
Exception in thread "main" java.lang.IllegalThreadStateException

22
What if we call Java run() method directly instead
start() method?
o Each thread starts in a separate call stack.
o Invoking the run() method from the main thread, the run() method goes onto the
current call stack rather than at the beginning of a new call stack.

FileName: TestCallRun1.java

1. class TestCallRun1 extends Thread{


2. public void run(){
3. System.out.println("running...");
4. }
5. public static void main(String args[]){
6. TestCallRun1 t1=new TestCallRun1();
7. t1.run();//fine, but does not start a separate call stack
8. }
9. }

Output:

running...

Problem if you direct call run() method

FileName: TestCallRun2.java

1. class TestCallRun2 extends Thread{


2. public void run(){
3. for(int i=1;i<5;i++){
4. try{Thread.sleep(500);}catch(InterruptedException e){System.out.println(e);}
5. System.out.println(i);
6. }
7. }
8. public static void main(String args[]){
9. TestCallRun2 t1=new TestCallRun2();

23
10. TestCallRun2 t2=new TestCallRun2();
11.
12. t1.run();
13. t2.run();
14. }
15. }

Output:

1
2
3
4
1
2
3
4

As we can see in the above program that there is no context-switching because here t1
and t2 will be treated as normal object not thread object.

Java join() method


The join() method in Java is provided by the java.lang.Thread class that permits one thread
to wait until the other thread to finish its execution. Suppose th be the object the class
Thread whose thread is doing its execution currently, then the th.join(); statement ensures
that th is finished before the program does the execution of the next statement. When
there are more than one thread invoking the join() method, then it leads to overloading
on the join() method that permits the developer or programmer to mention the waiting
period. However, similar to the sleep() method in Java, the join() method is also dependent
on the operating system for the timing, so we should not assume that the join() method
waits equal to the time we mention in the parameters. The following are the three
overloaded join() methods.

Description of The Overloaded join() Method


join(): When the join() method is invoked, the current thread stops its execution and the
thread goes into the wait state. The current thread remains in the wait state until the
thread on which the join() method is invoked has achieved its dead state. If interruption
of the thread occurs, then it throws the InterruptedException.

24
Syntax:

1. public final void join() throws InterruptedException

join(long mls): When the join() method is invoked, the current thread stops its execution
and the thread goes into the wait state. The current thread remains in the wait state until
the thread on which the join() method is invoked called is dead or the wait for the specified
time frame(in milliseconds) is over.

Syntax:

1. public final synchronized void join(long mls) throws InterruptedException, where mls is in mill
iseconds

join(long mls, int nanos): When the join() method is invoked, the current thread stops
its execution and go into the wait state. The current thread remains in the wait state until
the thread on which the join() method is invoked called is dead or the wait for the specified
time frame(in milliseconds + nanos) is over.

Syntax:

1. public final synchronized void join(long mls, int nanos) throws InterruptedException, where
mls is in milliseconds.

Example of join() Method in Java


The following program shows the usage of the join() method.

FileName: ThreadJoinExample.java

1. // A Java program for understanding


2. // the joining of threads
3.
4. // import statement
5. import java.io.*;
6.
7. // The ThreadJoin class is the child class of the class Thread

25
8. class ThreadJoin extends Thread
9. {
10. // overriding the run method
11. public void run()
12. {
13. for (int j = 0; j < 2; j++)
14. {
15. try
16. {
17. // sleeping the thread for 300 milli seconds
18. Thread.sleep(300);
19. System.out.println("The current thread name is: " + Thread.currentThread().getName());
20. }
21. // catch block for catching the raised exception
22. catch(Exception e)
23. {
24. System.out.println("The exception has been caught: " + e);
25. }
26. System.out.println( j );
27. }
28. }
29. }
30.
31. public class ThreadJoinExample
32. {
33. // main method
34. public static void main (String argvs[])
35. {
36.
37. // creating 3 threads
38. ThreadJoin th1 = new ThreadJoin();
39. ThreadJoin th2 = new ThreadJoin();
40. ThreadJoin th3 = new ThreadJoin();
41.

26
42. // thread th1 starts
43. th1.start();
44.
45. // starting the second thread after when
46. // the first thread th1 has ended or died.
47. try
48. {
49. System.out.println("The current thread name is: "+ Thread.currentThread().getName());
50.
51. // invoking the join() method
52. th1.join();
53. }
54.
55. // catch block for catching the raised exception
56. catch(Exception e)
57. {
58. System.out.println("The exception has been caught " + e);
59. }
60.
61. // thread th2 starts
62. th2.start();
63.
64. // starting the th3 thread after when the thread th2 has ended or died.
65. try
66. {
67. System.out.println("The current thread name is: " + Thread.currentThread().getName());
68. th2.join();
69. }
70.
71. // catch block for catching the raised exception
72. catch(Exception e)
73. {
74. System.out.println("The exception has been caught " + e);
75. }

27
76.
77. // thread th3 starts
78. th3.start();
79. }
80. }

Output:

The current thread name is: main


The current thread name is: Thread - 0
0
The current thread name is: Thread - 0
1
The current thread name is: main
The current thread name is: Thread - 1
0
The current thread name is: Thread - 1
1
The current thread name is: Thread - 2
0
The current thread name is: Thread - 2
1

Explanation: The above program shows that the second thread th2 begins after the first
thread th1 has ended, and the thread th3 starts its work after the second thread th2 has
ended or died.

The Join() Method: InterruptedException


We have learnt in the description of the join() method that whenever the interruption of
the thread occurs, it leads to the throwing of InterruptedException. The following example
shows the same.

FileName: ThreadJoinExample1.java

1. class ABC extends Thread


2. {
3. Thread threadToInterrupt;
4. // overriding the run() method
5. public void run()
6. {
7. // invoking the method interrupt

28
8. threadToInterrupt.interrupt();
9. }
10. }
11.
12.
13. public class ThreadJoinExample1
14. {
15. // main method
16. public static void main(String[] argvs)
17. {
18. try
19. {
20. // creating an object of the class ABC
21. ABC th1 = new ABC();
22.
23. th1.threadToInterrupt = Thread.currentThread();
24. th1.start();
25.
26. // invoking the join() method leads
27. // to the generation of InterruptedException
28. th1.join();
29. }
30. catch (InterruptedException ex)
31. {
32. System.out.println("The exception has been caught. " + ex);
33. }
34. }
35. }

Output:

The exception has been caught. java.lang.InterruptedException

Some More Examples of the join() Method


Let' see some other examples.

29
Filename: TestJoinMethod1.java

1. class TestJoinMethod1 extends Thread{


2. public void run(){
3. for(int i=1;i<=5;i++){
4. try{
5. Thread.sleep(500);
6. }catch(Exception e){System.out.println(e);}
7. System.out.println(i);
8. }
9. }
10. public static void main(String args[]){
11. TestJoinMethod1 t1=new TestJoinMethod1();
12. TestJoinMethod1 t2=new TestJoinMethod1();
13. TestJoinMethod1 t3=new TestJoinMethod1();
14. t1.start();
15. try{
16. t1.join();
17. }catch(Exception e){System.out.println(e);}
18.
19. t2.start();
20. t3.start();
21. }
22. }

Output:

1
2
3
4
5
1
1
2
2
3
3

30
4
4
5
5

We can see in the above example, when t1 completes its task then t2 and t3 starts
executing.

join(long miliseconds) Method Example


Filename: TestJoinMethod2.jav

1. class TestJoinMethod2 extends Thread{


2. public void run(){
3. for(int i=1;i<=5;i++){
4. try{
5. Thread.sleep(500);
6. }catch(Exception e){System.out.println(e);}
7. System.out.println(i);
8. }
9. }
10. public static void main(String args[]){
11. TestJoinMethod2 t1=new TestJoinMethod2();
12. TestJoinMethod2 t2=new TestJoinMethod2();
13. TestJoinMethod2 t3=new TestJoinMethod2();
14. t1.start();
15. try{
16. t1.join(1500);
17. }catch(Exception e){System.out.println(e);}
18.
19. t2.start();
20. t3.start();
21. }
22. }

Output:

1
2

31
3
1
4
1
2
5
2
3
3
4
4
5
5

In the above example, when t1 completes its task for 1500 milliseconds(3 times), then t2
and t3 start executing.

Naming Thread and Current Thread


Naming Thread
The Thread class provides methods to change and get the name of a thread. By default,
each thread has a name, i.e. thread-0, thread-1 and so on. By we can change the name of
the thread by using the setName() method. The syntax of setName() and getName()
methods are given below:

1. public String getName(): is used to return the name of a thread.


2. public void setName(String name): is used to change the name of a thread.

We can also set the name of a thread directly when we create a new thread using the
constructor of the class.

Example of naming a thread : Using setName() Method


FileName: TestMultiNaming1.java

1. class TestMultiNaming1 extends Thread{


2. public void run(){
3. System.out.println("running...");
4. }
5. public static void main(String args[]){
6. TestMultiNaming1 t1=new TestMultiNaming1();

32
7. TestMultiNaming1 t2=new TestMultiNaming1();
8. System.out.println("Name of t1:"+t1.getName());
9. System.out.println("Name of t2:"+t2.getName());
10.
11. t1.start();
12. t2.start();
13.
14. t1.setName("Sonoo Jaiswal");
15. System.out.println("After changing name of t1:"+t1.getName());
16. }
17. }

Output:

Name of t1:Thread-0
Name of t2:Thread-1
After changing name of t1:Sonoo Jaiswal
running...
running...
Example of naming a thread : Without Using setName()
Method
One can also set the name of a thread at the time of the creation of a thread, without
using the setName() method. Observe the following code.

FileName: ThreadNamingExample.java

1. // A Java program that shows how one can


2. // set the name of a thread at the time
3. // of creation of the thread
4.
5. // import statement
6. import java.io.*;
7.
8. // The ThreadNameClass is the child class of the class Thread
9. class ThreadName extends Thread
10. {
11.

33
12. // constructor of the class
13. ThreadName(String threadName)
14. {
15. // invoking the constructor of
16. // the superclass, which is Thread class.
17. super(threadName);
18. }
19.
20. // overriding the method run()
21. public void run()
22. {
23. System.out.println(" The thread is executing....");
24. }
25. }
26.
27. public class ThreadNamingExample
28. {
29. // main method
30. public static void main (String argvs[])
31. {
32. // creating two threads and settting their name
33. // using the contructor of the class
34. ThreadName th1 = new ThreadName("JavaTpoint1");
35. ThreadName th2 = new ThreadName("JavaTpoint2");
36.
37. // invoking the getName() method to get the names
38. // of the thread created above
39. System.out.println("Thread - 1: " + th1.getName());
40. System.out.println("Thread - 2: " + th2.getName());
41.
42.
43. // invoking the start() method on both the threads
44. th1.start();
45. th2.start();

34
46. }
47. }

Output:

Thread - 1: JavaTpoint1
Thread - 2: JavaTpoint2
The thread is executing....
The thread is executing....

Current Thread
The currentThread() method returns a reference of the currently executing thread.

1. public static Thread currentThread()


Example of currentThread() method
FileName: TestMultiNaming2.java

1. class TestMultiNaming2 extends Thread{


2. public void run(){
3. System.out.println(Thread.currentThread().getName());
4. }
5. public static void main(String args[]){
6. TestMultiNaming2 t1=new TestMultiNaming2();
7. TestMultiNaming2 t2=new TestMultiNaming2();
8.
9. t1.start();
10. t2.start();
11. }
12. }

Output:

Thread-0
Thread-1

Priority of a Thread (Thread Priority)


35
Each thread has a priority. Priorities are represented by a number between 1 and 10. In
most cases, the thread scheduler schedules the threads according to their priority (known
as preemptive scheduling). But it is not guaranteed because it depends on JVM
specification that which scheduling it chooses. Note that not only JVM a Java programmer
can also assign the priorities of a thread explicitly in a Java program.

Setter & Getter Method of Thread Priority


Let's discuss the setter and getter method of the thread priority.

public final int getPriority(): The java.lang.Thread.getPriority() method returns the


priority of the given thread.

public final void setPriority(int newPriority): The java.lang.Thread.setPriority() method


updates or assign the priority of the thread to newPriority. The method throws
IllegalArgumentException if the value newPriority goes out of the range, which is 1
(minimum) to 10 (maximum).

3 constants defined in Thread class:


1. public static int MIN_PRIORITY
2. public static int NORM_PRIORITY
3. public static int MAX_PRIORITY

Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and


the value of MAX_PRIORITY is 10.

Example of priority of a Thread:


FileName: ThreadPriorityExample.java

1. // Importing the required classes


2. import java.lang.*;
3.
4. public class ThreadPriorityExample extends Thread
5. {
6.
7. // Method 1

36
8. // Whenever the start() method is called by a thread
9. // the run() method is invoked
10. public void run()
11. {
12. // the print statement
13. System.out.println("Inside the run() method");
14. }
15.
16. // the main method
17. public static void main(String argvs[])
18. {
19. // Creating threads with the help of ThreadPriorityExample class
20. ThreadPriorityExample th1 = new ThreadPriorityExample();
21. ThreadPriorityExample th2 = new ThreadPriorityExample();
22. ThreadPriorityExample th3 = new ThreadPriorityExample();
23.
24. // We did not mention the priority of the thread.
25. // Therefore, the priorities of the thread is 5, the default value
26.
27. // 1st Thread
28. // Displaying the priority of the thread
29. // using the getPriority() method
30. System.out.println("Priority of the thread th1 is : " + th1.getPriority());
31.
32. // 2nd Thread
33. // Display the priority of the thread
34. System.out.println("Priority of the thread th2 is : " + th2.getPriority());
35.
36. // 3rd Thread
37. // // Display the priority of the thread
38. System.out.println("Priority of the thread th2 is : " + th2.getPriority());
39.
40. // Setting priorities of above threads by
41. // passing integer arguments

37
42. th1.setPriority(6);
43. th2.setPriority(3);
44. th3.setPriority(9);
45.
46. // 6
47. System.out.println("Priority of the thread th1 is : " + th1.getPriority());
48.
49. // 3
50. System.out.println("Priority of the thread th2 is : " + th2.getPriority());
51.
52. // 9
53. System.out.println("Priority of the thread th3 is : " + th3.getPriority());
54.
55. // Main thread
56.
57. // Displaying name of the currently executing thread
58. System.out.println("Currently Executing The Thread : " + Thread.currentThread().getName());
59.
60. System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());
61.
62. // Priority of the main thread is 10 now
63. Thread.currentThread().setPriority(10);
64.
65. System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());
66. }
67. }

Output:

Priority of the thread th1 is : 5


Priority of the thread th2 is : 5
Priority of the thread th2 is : 5
Priority of the thread th1 is : 6
Priority of the thread th2 is : 3
Priority of the thread th3 is : 9
Currently Executing The Thread : main
Priority of the main thread is : 5
Priority of the main thread is : 10

38
We know that a thread with high priority will get preference over lower priority threads
when it comes to the execution of threads. However, there can be other scenarios where
two threads can have the same priority. All of the processing, in order to look after the
threads, is done by the Java thread scheduler. Refer to the following example to
comprehend what will happen if two threads have the same priority.

FileName: ThreadPriorityExample1.java

1. // importing the java.lang package


2. import java.lang.*;
3.
4. public class ThreadPriorityExample1 extends Thread
5. {
6.
7. // Method 1
8. // Whenever the start() method is called by a thread
9. // the run() method is invoked
10. public void run()
11. {
12. // the print statement
13. System.out.println("Inside the run() method");
14. }
15.
16.
17. // the main method
18. public static void main(String argvs[])
19. {
20.
21. // Now, priority of the main thread is set to 7
22. Thread.currentThread().setPriority(7);
23.
24. // the current thread is retrieved
25. // using the currentThread() method
26.
27. // displaying the main thread priority

39
28. // using the getPriority() method of the Thread class
29. System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());
30.
31. // creating a thread by creating an object of the class ThreadPriorityExample1
32. ThreadPriorityExample1 th1 = new ThreadPriorityExample1();
33.
34. // th1 thread is the child of the main thread
35. // therefore, the th1 thread also gets the priority 7
36.
37. // Displaying the priority of the current thread
38. System.out.println("Priority of the thread th1 is : " + th1.getPriority());
39. }
40. }

Output:

Priority of the main thread is : 7


Priority of the thread th1 is : 7

Explanation: If there are two threads that have the same priority, then one can not predict
which thread will get the chance to execute first. The execution then is dependent on the
thread scheduler's algorithm (First Come First Serve, Round-Robin, etc.)

Example of IllegalArgumentException
We know that if the value of the parameter newPriority of the method getPriority() goes
out of the range (1 to 10), then we get the IllegalArgumentException. Let's observe the
same with the help of an example.

FileName: IllegalArgumentException.java

1. // importing the java.lang package


2. import java.lang.*;
3.
4. public class IllegalArgumentException extends Thread
5. {
6.
7. // the main method

40
8. public static void main(String argvs[])
9. {
10.
11. // Now, priority of the main thread is set to 17, which is greater than 10
12. Thread.currentThread().setPriority(17);
13.
14. // The current thread is retrieved
15. // using the currentThread() method
16.
17. // displaying the main thread priority
18. // using the getPriority() method of the Thread class
19. System.out.println("Priority of the main thread is : " + Thread.currentThread().getPriority());
20.
21. }
22. }

When we execute the above program, we get the following exception:

Exception in thread "main" java.lang.IllegalArgumentException


at java.base/java.lang.Thread.setPriority(Thread.java:1141)
at IllegalArgumentException.main(IllegalArgumentException.java:12)

Daemon Thread in Java


Daemon thread in Java is a service provider thread that provides services to the user
thread. Its life depend on the mercy of user threads i.e. when all the user threads dies,
JVM terminates this thread automatically.

There are many java daemon threads running automatically e.g. gc, finalizer etc.

You can see all the detail by typing the jconsole in the command prompt. The jconsole
tool provides information about the loaded classes, memory usage, running threads etc.

Points to remember for Daemon Thread in Java


o It provides services to user threads for background supporting tasks. It has no role in life
than to serve user threads.

41
o Its life depends on user threads.
o It is a low priority thread.

Why JVM terminates the daemon thread if there is no user


thread?
The sole purpose of the daemon thread is that it provides services to user thread for
background supporting task. If there is no user thread, why should JVM keep running this
thread. That is why JVM terminates the daemon thread if there is no user thread.

Methods for Java Daemon thread by Thread class


The java.lang.Thread class provides two methods for java daemon thread.

No. Method Description

1) public void setDaemon(boolean is used to mark the current thread as daemon thread or user
status) thread.

2) public boolean isDaemon() is used to check that current is daemon.

Simple example of Daemon thread in java


File: MyThread.java

1. public class TestDaemonThread1 extends Thread{


2. public void run(){
3. if(Thread.currentThread().isDaemon()){//checking for daemon thread
4. System.out.println("daemon thread work");
5. }
6. else{
7. System.out.println("user thread work");
8. }
9. }
10. public static void main(String[] args){
11. TestDaemonThread1 t1=new TestDaemonThread1();//creating thread

42
12. TestDaemonThread1 t2=new TestDaemonThread1();
13. TestDaemonThread1 t3=new TestDaemonThread1();
14.
15. t1.setDaemon(true);//now t1 is daemon thread
16.
17. t1.start();//starting threads
18. t2.start();
19. t3.start();
20. }
21. }

Output:

daemon thread work


user thread work
user thread work
Note: If you want to make a user thread as Daemon, it must not be started otherwise it
will throw IllegalThreadStateException.

File: MyThread.java

1. class TestDaemonThread2 extends Thread{


2. public void run(){
3. System.out.println("Name: "+Thread.currentThread().getName());
4. System.out.println("Daemon: "+Thread.currentThread().isDaemon());
5. }
6.
7. public static void main(String[] args){
8. TestDaemonThread2 t1=new TestDaemonThread2();
9. TestDaemonThread2 t2=new TestDaemonThread2();
10. t1.start();
11. t1.setDaemon(true);//will throw exception here
12. t2.start();
13. }
14. }

Output:

43
exception in thread main: java.lang.IllegalThreadStateException

Java Thread Pool


Java Thread pool represents a group of worker threads that are waiting for the job and
reused many times.

In the case of a thread pool, a group of fixed-size threads is created. A thread from the
thread pool is pulled out and assigned a job by the service provider. After completion of
the job, the thread is contained in the thread pool again.

Thread Pool Methods


newFixedThreadPool(int s): The method creates a thread pool of the fixed size s.

newCachedThreadPool(): The method creates a new thread pool that creates the new
threads when needed but will still use the previously created thread whenever they are
available to use.

newSingleThreadExecutor(): The method creates a new thread.

Advantage of Java Thread Pool


Better performance It saves time because there is no need to create a new thread.

Real time usage


It is used in Servlet and JSP where the container creates a thread pool to process the
request.

Example of Java Thread Pool


Let's see a simple example of the Java thread pool using ExecutorService and Executors.

File: WorkerThread.java

1. import java.util.concurrent.ExecutorService;

44
2. import java.util.concurrent.Executors;
3. class WorkerThread implements Runnable {
4. private String message;
5. public WorkerThread(String s){
6. this.message=s;
7. }
8. public void run() {
9. System.out.println(Thread.currentThread().getName()+" (Start) message = "+message);
10. processmessage();//call processmessage method that sleeps the thread for 2 seconds
11. System.out.println(Thread.currentThread().getName()+" (End)");//prints thread name
12. }
13. private void processmessage() {
14. try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
15. }
16. }

File: TestThreadPool.java

1. public class TestThreadPool {


2. public static void main(String[] args) {
3. ExecutorService executor = Executors.newFixedThreadPool(5);//creating a pool of 5 threads
4. for (int i = 0; i < 10; i++) {
5. Runnable worker = new WorkerThread("" + i);
6. executor.execute(worker);//calling execute method of ExecutorService
7. }
8. executor.shutdown();
9. while (!executor.isTerminated()) { }
10.
11. System.out.println("Finished all threads");
12. }
13. }

Output:

pool-1-thread-1 (Start) message = 0


pool-1-thread-2 (Start) message = 1

45
pool-1-thread-3 (Start) message = 2
pool-1-thread-5 (Start) message = 4
pool-1-thread-4 (Start) message = 3
pool-1-thread-2 (End)
pool-1-thread-2 (Start) message = 5
pool-1-thread-1 (End)
pool-1-thread-1 (Start) message = 6
pool-1-thread-3 (End)
pool-1-thread-3 (Start) message = 7
pool-1-thread-4 (End)
pool-1-thread-4 (Start) message = 8
pool-1-thread-5 (End)
pool-1-thread-5 (Start) message = 9
pool-1-thread-2 (End)
pool-1-thread-1 (End)
pool-1-thread-4 (End)
pool-1-thread-3 (End)
pool-1-thread-5 (End)
Finished all threads

Thread Pool Example: 2


Let's see another example of the thread pool.

FileName: ThreadPoolExample.java

1. // important import statements


2. import java.util.Date;
3. import java.util.concurrent.ExecutorService;
4. import java.util.concurrent.Executors;
5. import java.text.SimpleDateFormat;
6.
7.
8. class Tasks implements Runnable
9. {
10. private String taskName;
11.
12. // constructor of the class Tasks
13. public Tasks(String str)

46
14. {
15. // initializing the field taskName
16. taskName = str;
17. }
18.
19. // Printing the task name and then sleeps for 1 sec
20. // The complete process is getting repeated five times
21. public void run()
22. {
23. try
24. {
25. for (int j = 0; j <= 5; j++)
26. {
27. if (j == 0)
28. {
29. Date dt = new Date();
30. SimpleDateFormat sdf = new SimpleDateFormat("hh : mm : ss");
31.
32. //prints the initialization time for every task
33. System.out.println("Initialization time for the task name: "+ taskName + " = " + sdf.format(dt));
34.
35. }
36. else
37. {
38. Date dt = new Date();
39. SimpleDateFormat sdf = new SimpleDateFormat("hh : mm : ss");
40.
41. // prints the execution time for every task
42. System.out.println("Time of execution for the task name: " + taskName + " = " +sdf.format(dt));
43.
44. }
45.
46. // 1000ms = 1 sec
47. Thread.sleep(1000);

47
48. }
49.
50. System.out.println(taskName + " is complete.");
51. }
52.
53. catch(InterruptedException ie)
54. {
55. ie.printStackTrace();
56. }
57. }
58. }
59.
60. public class ThreadPoolExample
61. {
62. // Maximum number of threads in the thread pool
63. static final int MAX_TH = 3;
64.
65. // main method
66. public static void main(String argvs[])
67. {
68. // Creating five new tasks
69. Runnable rb1 = new Tasks("task 1");
70. Runnable rb2 = new Tasks("task 2");
71. Runnable rb3 = new Tasks("task 3");
72. Runnable rb4 = new Tasks("task 4");
73. Runnable rb5 = new Tasks("task 5");
74.
75. // creating a thread pool with MAX_TH number of
76. // threads size the pool size is fixed
77. ExecutorService pl = Executors.newFixedThreadPool(MAX_TH);
78.
79. // passes the Task objects to the pool to execute (Step 3)
80. pl.execute(rb1);
81. pl.execute(rb2);

48
82. pl.execute(rb3);
83. pl.execute(rb4);
84. pl.execute(rb5);
85.
86. // pool is shutdown
87. pl.shutdown();
88. }
89. }

Output:

Initialization time for the task name: task 1 = 06 : 13 : 02


Initialization time for the task name: task 2 = 06 : 13 : 02
Initialization time for the task name: task 3 = 06 : 13 : 02
Time of execution for the task name: task 1 = 06 : 13 : 04
Time of execution for the task name: task 2 = 06 : 13 : 04
Time of execution for the task name: task 3 = 06 : 13 : 04
Time of execution for the task name: task 1 = 06 : 13 : 05
Time of execution for the task name: task 2 = 06 : 13 : 05
Time of execution for the task name: task 3 = 06 : 13 : 05
Time of execution for the task name: task 1 = 06 : 13 : 06
Time of execution for the task name: task 2 = 06 : 13 : 06
Time of execution for the task name: task 3 = 06 : 13 : 06
Time of execution for the task name: task 1 = 06 : 13 : 07
Time of execution for the task name: task 2 = 06 : 13 : 07
Time of execution for the task name: task 3 = 06 : 13 : 07
Time of execution for the task name: task 1 = 06 : 13 : 08
Time of execution for the task name: task 2 = 06 : 13 : 08
Time of execution for the task name: task 3 = 06 : 13 : 08
task 2 is complete.
Initialization time for the task name: task 4 = 06 : 13 : 09
task 1 is complete.
Initialization time for the task name: task 5 = 06 : 13 : 09
task 3 is complete.
Time of execution for the task name: task 4 = 06 : 13 : 10
Time of execution for the task name: task 5 = 06 : 13 : 10
Time of execution for the task name: task 4 = 06 : 13 : 11
Time of execution for the task name: task 5 = 06 : 13 : 11
Time of execution for the task name: task 4 = 06 : 13 : 12
Time of execution for the task name: task 5 = 06 : 13 : 12
Time of execution for the task name: task 4 = 06 : 13 : 13

49
Time of execution for the task name: task 5 = 06 : 13 : 13
Time of execution for the task name: task 4 = 06 : 13 : 14
Time of execution for the task name: task 5 = 06 : 13 : 14
task 4 is complete.
task 5 is complete.

Explanation: It is evident by looking at the output of the program that tasks 4 and 5 are
executed only when the thread has an idle thread. Until then, the extra tasks are put in
the queue.

The takeaway from the above example is when one wants to execute 50 tasks but is not
willing to create 50 threads. In such a case, one can create a pool of 10 threads. Thus, 10
out of 50 tasks are assigned, and the rest are put in the queue. Whenever any thread out
of 10 threads becomes idle, it picks up the 11th task. The other pending tasks are treated
the same way.

Risks involved in Thread Pools


The following are the risk involved in the thread pools.

Deadlock: It is a known fact that deadlock can come in any program that involves
multithreading, and a thread pool introduces another scenario of deadlock. Consider a
scenario where all the threads that are executing are waiting for the results from the
threads that are blocked and waiting in the queue because of the non-availability of
threads for the execution.

Thread Leakage: Leakage of threads occurs when a thread is being removed from the
pool to execute a task but is not returning to it after the completion of the task. For
example, when a thread throws the exception and the pool class is not able to catch this
exception, then the thread exits and reduces the thread pool size by 1. If the same thing
repeats a number of times, then there are fair chances that the pool will become empty,
and hence, there are no threads available in the pool for executing other requests.

Resource Thrashing: A lot of time is wasted in context switching among threads when
the size of the thread pool is very large. Whenever there are more threads than the
optimal number may cause the starvation problem, and it leads to resource thrashing.

Points to Remember
Do not queue the tasks that are concurrently waiting for the results obtained from the
other tasks. It may lead to a deadlock situation, as explained above.

50
Care must be taken whenever threads are used for the operation that is long-lived. It may
result in the waiting of thread forever and will finally lead to the leakage of the resource.

In the end, the thread pool has to be ended explicitly. If it does not happen, then the
program continues to execute, and it never ends. Invoke the shutdown() method on the
thread pool to terminate the executor. Note that if someone tries to send another task to
the executor after shutdown, it will throw a RejectedExecutionException.

One needs to understand the tasks to effectively tune the thread pool. If the given tasks
are contrasting, then one should look for pools for executing different varieties of tasks
so that one can properly tune them.

To reduce the probability of running JVM out of memory, one can control the maximum
threads that can run in JVM. The thread pool cannot create new threads after it has
reached the maximum limit.

A thread pool can use the same used thread if the thread has finished its execution. Thus,
the time and resources used for the creation of a new thread are saved.

Tuning the Thread Pool


The accurate size of a thread pool is decided by the number of available processors and
the type of tasks the threads have to execute. If a system has the P processors that have
only got the computation type processes, then the maximum size of the thread pool of P
or P + 1 achieves the maximum efficiency. However, the tasks may have to wait for I/O,
and in such a scenario, one has to take into consideration the ratio of the waiting time
(W) and the service time (S) for the request; resulting in the maximum size of the pool P
* (1 + W / S) for the maximum efficiency.

Conclusion
A thread pool is a very handy tool for organizing applications, especially on the server-
side. Concept-wise, a thread pool is very easy to comprehend. However, one may have to
look at a lot of issues when dealing with a thread pool. It is because the thread pool comes
with some risks involved it (risks are discussed above).

ThreadGroup in Java
Java provides a convenient way to group multiple threads in a single object. In such a way,
we can suspend, resume or interrupt a group of threads by a single method call.

51
Note: Now suspend(), resume() and stop() methods are deprecated.

Java thread group is implemented by java.lang.ThreadGroup class.

A ThreadGroup represents a set of threads. A thread group can also include the other
thread group. The thread group creates a tree in which every thread group except the
initial thread group has a parent.

A thread is allowed to access information about its own thread group, but it cannot access
the information about its thread group's parent thread group or any other thread groups.

Constructors of ThreadGroup class


There are only two constructors of ThreadGroup class.

No. Constructor Description

1) ThreadGroup(String name) creates a thread group with given name.

2) ThreadGroup(ThreadGroup parent, String creates a thread group with a given parent group and
name) name.

Methods of ThreadGroup class


There are many methods in ThreadGroup class. A list of ThreadGroup methods is given
below.

Let's see a code to group multiple threads.

1. ThreadGroup tg1 = new ThreadGroup("Group A");


2. Thread t1 = new Thread(tg1,new MyRunnable(),"one");
3. Thread t2 = new Thread(tg1,new MyRunnable(),"two");
4. Thread t3 = new Thread(tg1,new MyRunnable(),"three");

52
S.N. Modifier and Method Description
Type

1) void checkAccess() This method determines if the currently running thread


has permission to modify the thread group.

2) int activeCount() This method returns an estimate of the number of active


threads in the thread group and its subgroups.

3) int activeGroupCount() This method returns an estimate of the number of active


groups in the thread group and its subgroups.

4) void destroy() This method destroys the thread group and all of its
subgroups.

5) int enumerate(Thread[] list) This method copies into the specified array every active
thread in the thread group and its subgroups.

6) int getMaxPriority() This method returns the maximum priority of the thread
group.

7) String getName() This method returns the name of the thread group.

8) ThreadGroup getParent() This method returns the parent of the thread group.

9) void interrupt() This method interrupts all threads in the thread group.

10) boolean isDaemon() This method tests if the thread group is a daemon thread
group.

11) void setDaemon(boolean This method changes the daemon status of the thread
daemon) group.

12) boolean isDestroyed() This method tests if this thread group has been
destroyed.

13) void list() This method prints information about the thread group
to the standard output.

53
14) boolean parentOf(ThreadGroup g This method tests if the thread group is either the thread
group argument or one of its ancestor thread groups.

15) void suspend() This method is used to suspend all threads in the thread
group.

16) void resume() This method is used to resume all threads in the thread
group which was suspended using suspend() method.

17) void setMaxPriority(int pri) This method sets the maximum priority of the group.

18) void stop() This method is used to stop all threads in the thread
group.

19) String toString() This method returns a string representation of the


Thread group.

Now all 3 threads belong to one group. Here, tg1 is the thread group name, MyRunnable
is the class that implements Runnable interface and "one", "two" and "three" are the
thread names.

Now we can interrupt all threads by a single line of code only.

1. Thread.currentThread().getThreadGroup().interrupt();

ThreadGroup Example
File: ThreadGroupDemo.java

1. public class ThreadGroupDemo implements Runnable{


2. public void run() {
3. System.out.println(Thread.currentThread().getName());
4. }
5. public static void main(String[] args) {
6. ThreadGroupDemo runnable = new ThreadGroupDemo();
7. ThreadGroup tg1 = new ThreadGroup("Parent ThreadGroup");

54
8.
9. Thread t1 = new Thread(tg1, runnable,"one");
10. t1.start();
11. Thread t2 = new Thread(tg1, runnable,"two");
12. t2.start();
13. Thread t3 = new Thread(tg1, runnable,"three");
14. t3.start();
15.
16. System.out.println("Thread Group Name: "+tg1.getName());
17. tg1.list();
18.
19. }
20. }

Output:

one
two
three
Thread Group Name: Parent ThreadGroup
java.lang.ThreadGroup[name=Parent ThreadGroup,maxpri=10]

Thread Pool Methods Example: int activeCount()


Let's see how one can use the method activeCount().

FileName: ActiveCountExample.java

1. // code that illustrates the activeCount() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class

55
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run method
17. public void run()
18. {
19.
20. for (int j = 0; j < 1000; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30. }
31. }
32. }
33.
34. public class ActiveCountExample
35. {
36. // main method
37. public static void main(String argvs[])
38. {
39. // creating the thread group
40. ThreadGroup tg = new ThreadGroup("The parent group of threads");
41.
42. ThreadNew th1 = new ThreadNew("first", tg);
43. System.out.println("Starting the first");

56
44.
45. ThreadNew th2 = new ThreadNew("second", tg);
46. System.out.println("Starting the second");
47.
48. // checking the number of active thread by invoking the activeCount() method
49. System.out.println("The total number of active threads are: " + tg.activeCount());
50. }
51. }

Output:

Starting the first


Starting the second
The total number of active threads are: 2

Thread Pool Methods Example: int activeGroupCount()


Now, we will learn how one can use the activeGroupCount() method in the code.

FileName: ActiveGroupCountExample.java

1. // Java code illustrating the activeGroupCount() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method

57
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class ActiveGroupCountExample
38. {
39. // main method
40. public static void main(String argvs[])
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("The parent group of threads");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);

58
51. System.out.println("Starting the second");
52.
53. // checking the number of active thread by invoking the activeGroupCount() method
54. System.out.println("The total number of active thread groups are: " + tg.activeGroupCount());
55. }
56. }

Output:

Starting the first


Starting the second
The total number of active thread groups are: 1
the second thread has finished executing
the first thread has finished executing

Thread Pool Methods Example: void destroy()


Now, we will learn how one can use the destroy() method in the code.

FileName: DestroyExample.java

1. // Code illustrating the destroy() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()

59
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class DestroyExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");

60
52.
53. // waiting until the other threads has been finished
54. th1.join();
55. th2.join();
56.
57. // destroying the child thread group
58. tg1.destroy();
59. System.out.println(tg1.getName() + " is destroyed.");
60.
61. // destroying the parent thread group
62. tg.destroy();
63. System.out.println(tg.getName() + " is destroyed.");
64. }
65. }

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.

Thread Pool Methods Example: int enumerate()


Now, we will learn how one can use the enumerate() method in the code.

FileName: EnumerateExample.java

1. // Code illustrating the enumerate() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread

61
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class EnumerateExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {

62
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. // returning the number of threads kept in this array
54. Thread[] grp = new Thread[tg.activeCount()];
55. int cnt = tg.enumerate(grp);
56. for (int j = 0; j < cnt; j++)
57. {
58. System.out.println("Thread " + grp[j].getName() + " is found.");
59. }
60. }
61. }

Output:

Starting the first


Starting the second
Thread the first is found.
Thread the second is found.
the first thread has finished executing
the second thread has finished executing

Thread Pool Methods Example: int getMaxPriority()


The following code shows the working of the getMaxPriority() method.

FileName: GetMaxPriorityExample.java

1. // Code illustrating the getMaxPriority() method

63
2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }

64
36.
37. public class GetMaxPriorityExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. int priority = tg.getMaxPriority();
54.
55. System.out.println("The maximum priority of the parent ThreadGroup: " + priority);
56.
57.
58. }
59. }

Output:

Starting the first


Starting the second
The maximum priority of the parent ThreadGroup: 10
the first thread has finished executing
the second thread has finished executing

Thread Pool Methods Example: ThreadGroup


getParent()

65
Now, we will learn how one can use the getParent() method in the code.

FileName: GetParentExample.java

1. // Code illustrating the getParent() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered" + e);
29. }
30.
31. }

66
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class GetMaxPriorityExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. // printing the parent ThreadGroup
54. // of both child and parent threads
55. System.out.println("The ParentThreadGroup for " + tg.getName() + " is " + tg.getParent().getNa
me());
56. System.out.println("The ParentThreadGroup for " + tg1.getName() + " is " + tg1.getParent().getN
ame());
57.
58.
59. }
60. }

Output:

Starting the first

67
Starting the second
The ParentThreadGroup for the parent group is main
The ParentThreadGroup for the child group is the parent group
the first thread has finished executing
the second thread has finished executing

Thread Pool Methods Example: void interrupt()


The following program illustrates how one can use the interrupt() method.

FileName: InterruptExample.java

1. // Code illustrating the interrupt() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);

68
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered " + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class InterruptExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. // invoking the interrupt method
54. tg.interrupt();
55.
56. }
57. }

69
Output:

Starting the first


Starting the second
The exception has been encountered java.lang.InterruptedException: sleep
interrupted
The exception has been encountered java.lang.InterruptedException: sleep
interrupted
the second thread has finished executing
the first thread has finished executing

Thread Pool Methods Example: boolean isDaemon()


The following program illustrates how one can use the isDaemon() method.

FileName: IsDaemonExample.java

1. // Code illustrating the isDaemon() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {

70
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered" + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class IsDaemonExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. if (tg.isDaemon() == true)
54. {
55. System.out.println("The group is a daemon group.");

71
56. }
57. else
58. {
59. System.out.println("The group is not a daemon group.");
60. }
61.
62. }
63. }

Output:

Starting the first


Starting the second
The group is not a daemon group.
the second thread has finished executing
the first thread has finished executing

Thread Pool Methods Example: boolean isDestroyed()


The following program illustrates how one can use the isDestroyed() method.

FileName: IsDestroyedExample.java

1. // Code illustrating the isDestroyed() method


2.
3. // import statement
4. import java.lang.*;
5.
6.
7. class ThreadNew extends Thread
8. {
9. // constructor of the class
10. ThreadNew(String tName, ThreadGroup tgrp)
11. {
12. super(tgrp, tName);
13. start();
14. }

72
15.
16. // overriding the run() method
17. public void run()
18. {
19.
20. for (int j = 0; j < 100; j++)
21. {
22. try
23. {
24. Thread.sleep(5);
25. }
26. catch (InterruptedException e)
27. {
28. System.out.println("The exception has been encountered" + e);
29. }
30.
31. }
32.
33. System.out.println(Thread.currentThread().getName() + " thread has finished executing");
34. }
35. }
36.
37. public class IsDestroyedExample
38. {
39. // main method
40. public static void main(String argvs[]) throws SecurityException, InterruptedException
41. {
42. // creating the thread group
43. ThreadGroup tg = new ThreadGroup("the parent group");
44.
45. ThreadGroup tg1 = new ThreadGroup(tg, "the child group");
46.
47. ThreadNew th1 = new ThreadNew("the first", tg);
48. System.out.println("Starting the first");

73
49.
50. ThreadNew th2 = new ThreadNew("the second", tg);
51. System.out.println("Starting the second");
52.
53. if (tg.isDestroyed() == true)
54. {
55. System.out.println("The group has been destroyed.");
56. }
57. else
58. {
59. System.out.println("The group has not been destroyed.");
60. }
61.
62. }
63. }

Output:

Starting the first


Starting the second
The group has not been destroyed.
the first thread has finished executing
the second thread has finished executing

74
Java Shutdown Hook
A special construct that facilitates the developers to add some code that has to be run
when the Java Virtual Machine (JVM) is shutting down is known as the Java shutdown
hook. The Java shutdown hook comes in very handy in the cases where one needs to
perform some special cleanup work when the JVM is shutting down. Note that handling
an operation such as invoking a special method before the JVM terminates does not work
using a general construct when the JVM is shutting down due to some external factors.
For example, whenever a kill request is generated by the operating system or due to
resource is not allocated because of the lack of free memory, then in such a case, it is not
possible to invoke the procedure. The shutdown hook solves this problem comfortably
by providing an arbitrary block of code.

Taking at a surface level, learning about the shutdown hook is straightforward. All one
has to do is to derive a class using the java.lang.Thread class, and then provide the code
for the task one wants to do in the run() method when the JVM is going to shut down.
For registering the instance of the derived class as the shutdown hook, one has to invoke
the method Runtime.getRuntime().addShutdownHook(Thread), whereas for removing the
already registered shutdown hook, one has to invoke the removeShutdownHook(Thread)
method.

In nutshell, the shutdown hook can be used to perform cleanup resources or save the
state when JVM shuts down normally or abruptly. Performing clean resources means
closing log files, sending some alerts, or something else. So if you want to execute some
code before JVM shuts down, use the shutdown hook.

When does the JVM shut down?


The JVM shuts down when:

75
o user presses ctrl+c on the command prompt
o System.exit(int) method is invoked
o user logoff
o user shutdown etc.

The addShutdownHook(Thread hook) method


The addShutdownHook() method of the Runtime class is used to register the thread with
the Virtual Machine.

Syntax:

1. public void addShutdownHook(Thread hook){}

The object of the Runtime class can be obtained by calling the static factory method
getRuntime(). For example:

1. Runtime r = Runtime.getRuntime();
The removeShutdownHook(Thread hook) method
The removeShutdownHook() method of the Runtime class is invoked to remove the
registration of the already registered shutdown hooks.

Syntax:

1. public boolean removeShutdownHook(Thread hook){ }

True value is returned by the method, when the method successfully de-register the
registered hooks; otherwise returns false.

Factory method
The method that returns the instance of a class is known as factory method.

Simple example of Shutdown Hook


FileName: MyThread.java

1. class MyThread extends Thread{

76
2. public void run(){
3. System.out.println("shut down hook task completed..");
4. }
5. }
6.
7. public class TestShutdown1{
8. public static void main(String[] args)throws Exception {
9.
10. Runtime r=Runtime.getRuntime();
11. r.addShutdownHook(new MyThread());
12.
13. System.out.println("Now main sleeping... press ctrl+c to exit");
14. try{Thread.sleep(3000);}catch (Exception e) {}
15. }
16. }

Output:

Now main sleeping... press ctrl+c to exit


shut down hook task completed.
Same example of Shutdown Hook by anonymous class:
FileName: TestShutdown2.java

1. public class TestShutdown2{


2. public static void main(String[] args)throws Exception {
3.
4. Runtime r=Runtime.getRuntime();
5.
6. r.addShutdownHook(new Thread(){
7. public void run(){
8. System.out.println("shut down hook task completed..");
9. }
10. }
11. );
12.

77
13. System.out.println("Now main sleeping... press ctrl+c to exit");
14. try{Thread.sleep(3000);}catch (Exception e) {}
15. }
16. }

Output:

Now main sleeping... press ctrl+c to exit


shut down hook task completed.
Removing the registered shutdown hook example
The following example shows how one can use the removeShutdownHook() method to
remove the registered shutdown hook.

FileName: RemoveHookExample.java

1. public class RemoveHookExample


2. {
3.
4. // the Msg class is derived from the Thread class
5. static class Msg extends Thread
6. {
7.
8. public void run()
9. {
10. System.out.println("Bye ...");
11. }
12. }
13.
14. // main method
15. public static void main(String[] argvs)
16. {
17. try
18. {
19. // creating an object of the class Msg
20. Msg ms = new Msg();
21.

78
22. // registering the Msg object as the shutdown hook
23. Runtime.getRuntime().addShutdownHook(ms);
24.
25. // printing the current state of program
26. System.out.println("The program is beginning ...");
27.
28. // causing the thread to sleep for 2 seconds
29. System.out.println("Waiting for 2 seconds ...");
30. Thread.sleep(2000);
31.
32. // removing the hook
33. Runtime.getRuntime().removeShutdownHook(ms);
34.
35. // printing the message program is terminating
36. System.out.println("The program is terminating ...");
37. }
38. catch (Exception ex)
39. {
40. ex.printStackTrace();
41. }
42. }
43. }

Output:

The program is beginning ...


Waiting for 2 seconds ...
The program is terminating ...

Points to Remember
There are some important points to keep in mind while working with the shutdown hook.

No guarantee for the execution of the shutdown hooks: The first and the most important
thing to keep in mind is that there is no certainty about the execution of the shutdown
hook. In some scenarios, the shutdown hooks will not execute at all. For example, if the
JVM gets crashed due to some internal error, then there is no scope for the shutdown

79
hooks. When the operating system gives the SYSKILL signal, then also it is not possible
for the shutdown hooks to come into picture.

Note that when the application is terminated normally the shutdown hooks are called (all
threads of the application is finished or terminated). Also, when the operating system is
shut down or the user presses the ctrl + c the shutdown hooks are invoked.

Before completion, the shutdown hooks can be stopped forcefully: It is a special case of
the above discussed point. Whenever a shutdown hooks start to execute, one can
forcefully terminate it by shutting down the system. In this case, the operating system for
a specific amount of time. If the job is not done in that frame of time, then the system has
no other choice than to forcefully terminate the running hooks.

There can be more than one shutdown hooks, but there execution order is not
guaranteed: The JVM can execute the shutdown hooks in any arbitrary order. Even
concurrent execution of the shutdown hooks are also possible.

Within shutdown hooks, it is not allowed to unregister or register the shutdown hooks:
When the JVM initiates the shutdown sequence, one can not remove or add more any
existing shutdown hooks. If one tries to do so, the IllegalStateException is thrown by the
JVM.

The Runtime.halt() can stop the shutdown sequence that has been started: Only the
Runtime.halt(), which terminates the JVM forcefully, can stop the started shutdown
sequence, which also means that invoking the System.exit() method will not work within
a shutdown hook.

Security permissions are required when using shutdown hooks: If one is using the Java
Security Managers, then the Java code that is responsible for removing or adding the
shutdown hooks need to get the shutdown hooks permission at the runtime. If one
invokes the method without getting the permission in the secure environment, then it will
raise the SecurityException.

80
How to perform single task by multiple threads in
Java?
If you have to perform a single task by many threads, have only one run() method. For
example:

Program of performing single task by multiple threads


FileName: TestMultitasking1.java

1. class TestMultitasking1 extends Thread{


2. public void run(){
3. System.out.println("task one");
4. }
5. public static void main(String args[]){
6. TestMultitasking1 t1=new TestMultitasking1();
7. TestMultitasking1 t2=new TestMultitasking1();
8. TestMultitasking1 t3=new TestMultitasking1();
9.
10. t1.start();
11. t2.start();
12. t3.start();
13. }
14. }

Output:

task one
task one

81
task one
Program of performing single task by multiple threads
FileName: TestMultitasking2.java

1. class TestMultitasking2 implements Runnable{


2. public void run(){
3. System.out.println("task one");
4. }
5.
6. public static void main(String args[]){
7. Thread t1 =new Thread(new TestMultitasking2());//passing annonymous object of TestMultitask
ing2 class
8. Thread t2 =new Thread(new TestMultitasking2());
9.
10. t1.start();
11. t2.start();
12.
13. }
14. }

Output:

task one
task one
Note: Each thread run in a separate callstack.

82
How to perform multiple tasks by multiple threads
(multitasking in multithreading)?
If you have to perform multiple tasks by multiple threads,have multiple run() methods.For
example:

Program of performing two tasks by two threads

FileName: TestMultitasking3.java

1. class Simple1 extends Thread{


2. public void run(){
3. System.out.println("task one");
4. }
5. }
6.
7. class Simple2 extends Thread{
8. public void run(){
9. System.out.println("task two");
10. }
11. }
12.
13. class TestMultitasking3{
14. public static void main(String args[]){
15. Simple1 t1=new Simple1();
16. Simple2 t2=new Simple2();
17.
18. t1.start();
19. t2.start();
20. }
21. }

Output:

83
task one
task two
Same example as above by anonymous class that extends
Thread class:
Program of performing two tasks by two threads

FileName: TestMultitasking4.java

1. class TestMultitasking4{
2. public static void main(String args[]){
3. Thread t1=new Thread(){
4. public void run(){
5. System.out.println("task one");
6. }
7. };
8. Thread t2=new Thread(){
9. public void run(){
10. System.out.println("task two");
11. }
12. };
13.
14.
15. t1.start();
16. t2.start();
17. }
18. }

Output:

task one
task two
Same example as above by anonymous class that implements
Runnable interface:
Program of performing two tasks by two threads

84
FileName: TestMultitasking5.java

1. class TestMultitasking5{
2. public static void main(String args[]){
3. Runnable r1=new Runnable(){
4. public void run(){
5. System.out.println("task one");
6. }
7. };
8.
9. Runnable r2=new Runnable(){
10. public void run(){
11. System.out.println("task two");
12. }
13. };
14.
15. Thread t1=new Thread(r1);
16. Thread t2=new Thread(r2);
17.
18. t1.start();
19. t2.start();
20. }
21. }

Output:

task one
task two
Printing even and odd numbers using two threads
To print the even and odd numbers using the two threads, we will use the synchronized
block and the notify() method. Observe the following program.

FileName: OddEvenExample.java

1. // Java program that prints the odd and even numbers using two threads.
2. // the time complexity of the program is O(N), where N is the number up to which we

85
3. // are displaying the numbers
4. public class OddEvenExample
5. {
6. // Starting the counter
7. int contr = 1;
8. static int NUM;
9. // Method for printing the odd numbers
10. public void displayOddNumber()
11. {
12. // note that synchronized blocks are necessary for the code for getting the desired
13. // output. If we remove the synchronized blocks, we will get an exception.
14. synchronized (this)
15. {
16. // Printing the numbers till NUM
17. while (contr < NUM)
18. {
19. // If the contr is even then display
20. while (contr % 2 == 0)
21. {
22. // handling the exception handle
23. try
24. {
25. wait();
26. }
27. catch (InterruptedException ex)
28. {
29. ex.printStackTrace();
30. }
31. }
32. // Printing the number
33. System.out.print(contr + " ");
34. // Incrementing the contr
35. contr = contr + 1;
36. // notifying the thread which is waiting for this lock

86
37. notify();
38. }
39. }
40. }
41. // Method for printing the even numbers
42. public void displayEvenNumber()
43. {
44. synchronized (this)
45. {
46. // Printing the number till NUM
47. while (contr < NUM)
48. {
49. // If the count is odd then display
50. while (contr % 2 == 1)
51. {
52. // handling the exception
53. try
54. {
55. wait();
56. }
57. catch (InterruptedException ex)
58. {
59. ex.printStackTrace();
60. }
61. }
62. // Printing the number
63. System.out.print(contr + " ");
64. // Incrementing the contr
65. contr = contr +1;
66. // Notifying to the 2nd thread
67. notify();
68. }
69. }
70. }

87
71. // main method
72. public static void main(String[] argvs)
73. {
74. // The NUM is given
75. NUM = 20;
76. // creating an object of the class OddEvenExample
77. OddEvenExample oe = new OddEvenExample();
78. // creating a thread th1
79. Thread th1 = new Thread(new Runnable()
80. {
81. public void run()
82. {
83. // invoking the method displayEvenNumber() using the thread th1
84. oe.displayEvenNumber();
85. }
86. });
87. // creating a thread th2
88. Thread th2 = new Thread(new Runnable()
89. {
90. public void run()
91. {
92. // invoking the method displayOddNumber() using the thread th2
93. oe.displayOddNumber();
94. }
95. });
96. // starting both of the threads
97. th1.start();
98. th2.start();
99. }
100. }

Output:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

88
Java Garbage Collection
In java, garbage means unreferenced objects.

Garbage Collection is process of reclaiming the runtime unused memory automatically. In


other words, it is a way to destroy the unused objects.

To do so, we were using free() function in C language and delete() in C++. But, in java it
is performed automatically. So, java provides better memory management.

Advantage of Garbage Collection


o It makes java memory efficient because garbage collector removes the unreferenced
objects from heap memory.
o It is automatically done by the garbage collector(a part of JVM) so we don't need to make
extra efforts.

How can an object be unreferenced?


There are many ways:

1) By nulling the reference

2) By assigning a reference to another

3) By anonymous object etc.

89
1) By nulling a reference:
1. Employee e=new Employee();
2. e=null;
2) By assigning a reference to another:
1. Employee e1=new Employee();
2. Employee e2=new Employee();
3. e1=e2;//now the first object referred by e1 is available for garbage collection
3) By anonymous object:
1. new Employee();

finalize() method
The finalize() method is invoked each time before the object is garbage collected. This
method can be used to perform cleanup processing. This method is defined in Object
class as:

90
1. protected void finalize(){}
Note: The Garbage collector of JVM collects only those objects that are created by new
keyword. So if you have created any object without new, you can use finalize method
to perform cleanup processing (destroying remaining objects).

gc() method
The gc() method is used to invoke the garbage collector to perform cleanup processing.
The gc() is found in System and Runtime classes.

1. public static void gc(){}


Note: Garbage collection is performed by a daemon thread called Garbage
Collector(GC). This thread calls the finalize() method before object is garbage
collected.

Simple Example of garbage collection in java


1. public class TestGarbage1{
2. public void finalize(){System.out.println("object is garbage collected");}
3. public static void main(String args[]){
4. TestGarbage1 s1=new TestGarbage1();
5. TestGarbage1 s2=new TestGarbage1();
6. s1=null;
7. s2=null;
8. System.gc();
9. }
10. }
object is garbage collected
object is garbage collected
Note: Neither finalization nor garbage collection is guaranteed.

Java Runtime class


Java Runtime class is used to interact with java runtime environment. Java Runtime class
provides methods to execute a process, invoke GC, get total and free memory etc. There
is only one instance of java.lang.Runtime class is available for one java application.

The Runtime.getRuntime() method returns the singleton instance of Runtime class.

91
Important methods of Java Runtime class

No. Method Description

1) public static Runtime getRuntime() returns the instance of Runtime class.

2) public void exit(int status) terminates the current virtual machine.

3) public void addShutdownHook(Thread hook) registers new hook thread.

4) public Process exec(String command)throws executes given command in a separate


IOException process.

5) public int availableProcessors() returns no. of available processors.

6) public long freeMemory() returns amount of free memory in JVM.

7) public long totalMemory() returns amount of total memory in JVM.

Java Runtime exec() method


1. public class Runtime1{
2. public static void main(String args[])throws Exception{
3. Runtime.getRuntime().exec("notepad");//will open a new notepad
4. }
5. }

How to shutdown system in Java


You can use shutdown -s command to shutdown system. For windows OS, you need to
provide full path of shutdown command e.g. c:\\Windows\\System32\\shutdown.

Here you can use -s switch to shutdown system, -r switch to restart system and -t switch
to specify time delay.

1. public class Runtime2{


2. public static void main(String args[])throws Exception{

92
3. Runtime.getRuntime().exec("shutdown -s -t 0");
4. }
5. }

How to shutdown windows system in Java


1. public class Runtime2{
2. public static void main(String args[])throws Exception{
3. Runtime.getRuntime().exec("c:\\Windows\\System32\\shutdown -s -t 0");
4. }
5. }

How to restart system in Java


1. public class Runtime3{
2. public static void main(String args[])throws Exception{
3. Runtime.getRuntime().exec("shutdown -r -t 0");
4. }
5. }

Java Runtime availableProcessors()


1. public class Runtime4{
2. public static void main(String args[])throws Exception{
3. System.out.println(Runtime.getRuntime().availableProcessors());
4. }
5. }

Java Runtime freeMemory() and totalMemory() method


In the given program, after creating 10000 instance, free memory will be less than the
previous free memory. But after gc() call, you will get more free memory.

1. public class MemoryTest{


2. public static void main(String args[])throws Exception{
3. Runtime r=Runtime.getRuntime();

93
4. System.out.println("Total Memory: "+r.totalMemory());
5. System.out.println("Free Memory: "+r.freeMemory());
6.
7. for(int i=0;i<10000;i++){
8. new MemoryTest();
9. }
10. System.out.println("After creating 10000 instance, Free Memory: "+r.freeMemory());
11. System.gc();
12. System.out.println("After gc(), Free Memory: "+r.freeMemory());
13. }
14. }
Total Memory: 100139008
Free Memory: 99474824
After creating 10000 instance, Free Memory: 99310552
After gc(), Free Memory: 100182832

94

You might also like