ognexception_threads
ognexception_threads
•At a time only one exception occurs and at a time only one catch block
is executed.
•All catch blocks must be ordered from most specific to most general,
i.e. catch for ArithmeticException must come before catch for
Exception.
Java Multi-catch block
public class CatchTest
{
public static void main(String[] args)
{
try
{
int a[]=new int[5];
a[5]=30/1;
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBounds Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs");
} O/P:
System.out.println("rest of the code"); ArrayIndexOutOfBounds Exception occurs
} rest of the code
}
public class CatchTest
{
public static void main(String[] args) try block contains two
{ exceptions. But at a time only
try{ one exception occurs and its
int a[]=new int[5]; corresponding catch block is
a[4]=30/0; executed.
System.out.println(a[10]);
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception
occurs");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBounds
Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs"); Output:
} Arithmetic Exception occurs
System.out.println("rest of the code"); rest of the code
}}
public class Test we generate NullPointerException, but
{ didn't provide the corresponding
public static void main(String[] args) exception type. In such case, the catch
{ block containing the parent exception
try class Exception will invoked.
{
String s=null;
System.out.println(s.length());
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("ArrayIndexOutOfBounds
Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs"); O/P:
} Parent Exception occurs
System.out.println("rest of the code"); rest of the code
}}
class Test
{
public static void main(String args[]
{
try{
int a[]=new int[5];
a[5]=30/0;
} without maintaining the order of exceptions
catch(Exception e) (i.e. from most specific to most general).
{
System.out.println("common task
completed");
}
catch(ArithmeticException e)
{
System.out.println("task1 is
completed");
}
catch(ArrayIndexOutOfBoundsExceptio
n e)
{
System.out.println("task 2 completed"); Output:
} Compile-time error
System.out.println("rest of the code...");
}}
Nested try
When any try block does not have a catch block for a particular exception:-
• catch block of the outer (parent) try block are checked for that exception, and
if it matches, the catch block of outer try block is executed.
If none of the catch block specified in the code is unable to handle the exception:- -
--Java runtime system will handle the exception.
try
{
System.out.println("Inside the try block");
Exception not handled
//below code throws divide by zero exception
int data=25/0;
System.out.println(data);
}
//cannot handle Arithmetic type exception
//can only accept Null Pointer type exception
catch(NullPointerException e){
System.out.println(e);
}
An exception is first thrown from the top of the stack and if it is not caught, it
drops down the call stack to the previous method. If not caught there, the
exception again drops down to the previous method, and so on until they are
caught or until they reach the very bottom of the call stack. This is called
exception propagation.
class Test
{ In the above example exception occurs in the m()
void m() method where it is not handled, so it is
{ propagated to the previous n() method where it is
int data=50/0; not handled, again it is propagated to the p()
}
method where exception is handled.
void n()
{
m();
}
void p()
{
try{
n();
}catch(Exception e)
{
System.out.println("exception handled");
}
}
public static void main(String args[])
{
Test ob=new Test();
ob.p(); Output:
System.out.println("normal flow..."); exception handled
}
normal flow...
}
class Test Checked exceptions are not propagated
{
void m()
{
throw new java.io.IOException("device error");//checked exception
}
void n()
{
m();
}
void p()
{
try
{
n();
}
catch(Exception e)
{
System.out.println("exception handeled");
}
}
public static void main(String args[])
{
Test ob=new Test();
ob.p(); Output:
System.out.println("normal flow"); Compile Time Error
}
}
Java throws keyword
• The Java throws keyword is used to declare an exception.
• It gives an information to the programmer that there may occur an
exception.
• exception handling code to be provided so that the normal flow of
the program can be maintained.
• Exception Handling is mainly used to handle the checked
exceptions.
• checked exceptions can be propagated by throws keyword.
import java.io.*;
class A{
void f()throws IOException{
throw new IOException("device error");
}
}
class Test{
public static void main(String args[])throws IOException
{//declare exception
A m=new M();
m.f();
System.out.println("normal flow...");
}
}
public class TestThrow
{
public static void checkNum(int num)
{
if (num < 1)
{
throw new ArithmeticException("\nNumber is negative, cannot calculate square");
}
else
{
System.out.println("Square of " + num + " is " + (num*num));
}
}
//main method
public static void main(String[] args) {
TestThrow obj = new TestThrow();
obj.checkNum(-3);
System.out.println("Rest of the code..");
}
}
public class TestThrows
{
public static int divideNum(int m, int n) throws ArithmeticException
{
int div = m / n;
return div;
}
try {
p.msg();
}
catch (Exception e){}
}
}
import java.io.*; Example in case subclass overridden
class Parent{ method declares same exception
void msg() throws Exception {
System.out.println("parent method");
}
}
try {
p.msg();
}
catch(Exception e) {}
}
}
import java.io.*; Example in case subclass overridden
class Parent{ method declares subclass exception
void msg()throws Exception {
System.out.println("parent method");
}
}
try {
p.msg();
}
catch(Exception e) {}
}
}
import java.io.*; Example in case subclass overridden
class Parent { method declares no exception
void msg()throws Exception{
System.out.println("parent method");
}
}
try {
p.msg();
}
catch(Exception e) {}
}
}
Custom Exception
Resource
Process Thread
• New
• Active
• Blocked / Waiting
• Timed Waiting
• Terminated
• All those threads that are willing to run, waiting for their
turn to run, lie in the runnable state.
• 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.
Life cycle of a Thread
• After the time runs out, the thread wakes up and start its
execution from when it has left earlier.
Life cycle of a Thread
Thread class:
• Thread class provide constructors and methods to create and perform
operations on a thread.
Starting a thread:
The start() method of Thread class is used to start a newly created thread.
It performs the following tasks:
•A new thread starts (with new callstack).
•The thread moves from New state to the Runnable state.
•When the thread gets a chance to execute, its target run() method will
run.
Thread Example by extending Thread class
thread is running...
Thread Example by implementing Runnable interface
thread is running...
Using the Thread Class: Thread(String Name)
We can directly use the Thread class to
public class Main spawn new threads
{
// Main method
public static void main(String argvs[])
{
// creating an object of the Thread class using the constructor Thread(String
name)
Thread t= new Thread("My first thread");
// main method
public static void main(String argvs[])
{
// creating an object of the class Main
Runnable r1 = new Main();
A component of Java that decides which thread to run or execute and which
thread to wait is called a thread scheduler in Java.
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. A thread that arrived first gets
the preference over the other threads.
Thread Scheduler Algorithms
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.
Preemptive-Priority Scheduling:
The Thread.sleep() method can be used with any thread. It means any other thread
or the main thread can invoke 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.
Thread.sleep() with examples
• 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.
class Test extends Thread
{
public void run()
{ .
for(int i=1;i<5;i++)
{
// the thread will sleep for the 500 milli seconds
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println(e);} Output:
System.out.println(i);
} 1
} 1
public static void main(String args[]) 2
{ 2
Test t1=new Test(); 3
Test t2=new Test(); 3
t1.start(); 4
t2.start(); 4
}
}
public class Main
{
// main method
public static void main(String argvs[]) .
{
try
{
for (int j = 0; j < 5; j++)
{
// The main thread sleeps for the 1000 milliseconds, which is 1 sec
// whenever the loop runs
Thread.sleep(1000);
// displaying the value of the variable
System.out.println(j);
}
} O/P:
catch (Exception expn)
{ 0
// catching the exception 1
System.out.println(expn); 2
} 3
} 4
}
public class Main
{
public static void main(String argvs[]) .
{
try
{
for (int j = 0; j < 5; j++)
{
// it throws the exception IllegalArgumentException
// as the time is -ive which is -100
Thread.sleep(-100);
System.out.println(j);
}
}
catch (Exception expn)
{
System.out.println(expn);
}
}
}
O/P:
java.lang.IllegalArgumentException: timeout value is negative
class TestCallRun1 extends Thread{
public void run() .
{
System.out.println("running...");
}
public static void main(String args[])
{
TestCallRun1 t1=new TestCallRun1();
t1.run();//fine, but does not start a separate call
stack
}
} Each thread starts in a separate call stack.
Output:
Invoking the run() method from the main
thread, the run() method goes onto the
running..
current call stack rather than at the
beginning of a new call stack.
class ThreadTest extends Thread Java code to see that all threads are
{
public void run()
pushed on same stack if we use run()
{ instead of start().
try
{
// Displaying the thread that is running
System.out.println ("Thread " +
Thread.currentThread().getId() +
" is running");
}
catch (Exception e)
{
System.out.println ("Exception is caught");
}
}
}
public class Main Output:
{ Thread 1 is running
public static void main(String[] args)
{ Thread 1 is running
int n = 8; Thread 1 is running
for (int i=0; i<8; i++) Thread 1 is running
{
ThreadTest object = new ThreadTest();
Thread 1 is running
Thread 1 is running
object.run(); Thread 1 is running
} Thread 1 is running
}
}
class ThreadTest extends Thread Java code to see that all threads are
{
public void run()
pushed on same stack if we use run()
{ instead of start().
try
{
// Displaying the thread that is running
System.out.println ("Thread " +
Thread.currentThread().getId() +
" is running");
}
catch (Exception e)
{
System.out.println ("Exception is caught");
}
}
}
public class Main Output:
{ Thread 12 is running
public static void main(String[] args)
{ Thread 18 is running
int n = 8; Thread 11 is running
for (int i=0; i<8; i++) Thread 13 is running
{
ThreadTest object = new ThreadTest();
Thread 15 is running
Thread 17 is running
object.start(); Thread 16 is running
} Thread 14 is running
}
}
Threads implement their own stack - demonstration using program and diagram
class TestCallRun2 extends Thread
{
public void run() here is no context-switching because here
{ t1 and t2 will be treated as normal object
for(int i=1;i<5;i++) not thread object.
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println(e);
} Output:
System.out.println(i); 1
} 2
} 3
public static void main(String args[]) 4
{ 1
TestCallRun2 t1=new TestCallRun2(); 2
TestCallRun2 t2=new TestCallRun2(); 3
t1.run(); 4
t2.run();
} }
class TestCallRun2 extends Thread
{
public void run() here is context-switching because here t1
{ and t2 will be treated as thread object.
for(int i=1;i<5;i++)
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println(e);
} Output:
System.out.println(i); 1
} 1
} 2
public static void main(String args[]) 2
{ 3
TestCallRun2 t1=new TestCallRun2(); 3
TestCallRun2 t2=new TestCallRun2(); 4
t1.start(); 4
t2.start();
} }
join() method
• 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.
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.
join() method
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:
public final synchronized void join(long mls) throws InterruptedException
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:
public final synchronized void join(long mls, int nanos) throws InterruptedException
import java.io.*;
import java.util.*;
th2.start();
th3.start();
}
O/P:
1
1
1
2
2
2
3
3
3
4
4
4
import java.io.*;
import java.util.*;
th2.start();
th3.start();
}
O/P:
1
2
3
4
1
2
3
4
1
2
3
4
import java.io.*; th1.start();
// starting the second thread after when
class ThreadJoin extends Thread // the first thread th1 has ended or died.
{ try
public void run() {
{ System.out.println("The current thread name is: "+
for (int j = 0; j < 2; j++) Thread.currentThread().getName());
{ // invoking the join() method
try th1.join();
{ }
Thread.sleep(300); catch(Exception e)
System.out.println("The current thread name is: " + {
Thread.currentThread().getName()); System.out.println("The exception has been caught " +
} e);
catch(Exception e) }
{ th2.start();
System.out.println("The exception has been caught: " + // starting the th3 thread after when the thread th2 has
e); ended or died.
} try
System.out.println( j ); {
} System.out.println("The current thread name is: " +
} Thread.currentThread().getName());
} th2.join();
public class ThreadJoinExample }
{ catch(Exception e)
public static void main (String argvs[]) {
{ System.out.println("The exception has been caught " +
ThreadJoin th1 = new ThreadJoin(); e);
ThreadJoin th2 = new ThreadJoin(); }
ThreadJoin th3 = new ThreadJoin(); th3.start();
}}
O/P
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.
class TestJoinMethod1 extends Thread
{ when t1 completes its task then t2 and t3
public void run() starts executing.
{
for(int i=1;i<=5;i++)
{
try{
Thread.sleep(500); O/P:
}catch(Exception e){System.out.println(e);} 1
System.out.println(i); 2
} 3
} 4
public static void main(String args[]){ 5
TestJoinMethod1 t1=new TestJoinMethod1(); 1
TestJoinMethod1 t2=new TestJoinMethod1(); 1
TestJoinMethod1 t3=new TestJoinMethod1(); 2
t1.start(); 2
try{ 3
t1.join(); 3
}catch(Exception e){System.out.println(e);} 4
4
t2.start(); 5
t3.start(); 5
}}
class TestJoinMethod2 extends Thread{ when t1 completes its task for 1500
public void run(){ milliseconds(3 times), then t2 and t3 start
for(int i=1;i<=5;i++){ executing.
try{
Thread.sleep(500);
}catch(Exception e){System.out.println(e);}
System.out.println(i); O/P: O/P:
} 1 1
} 2 2
public static void main(String args[]){ 3 3
TestJoinMethod2 t1=new TestJoinMethod2(); 1 1
TestJoinMethod2 t2=new TestJoinMethod2(); 4 1
TestJoinMethod2 t3=new TestJoinMethod2(); 1 4
t1.start(); 2 2
try{ 5 2
t1.join(1500); 2 5
}catch(Exception e){System.out.println(e);} 3 3
3 3
t2.start(); 4 4
t3.start(); 4 4
} } 5 5
5 5
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:
t1.start(); O/P:
t2.start();
} Thread-0
} Thread-1
Thread Priority
O/P:
Priority of the thread th1 is : 5
Priority of the thread th2 is : 5
Priority of the thread th3 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
// th1 thread is the child of the main
thread
import java.lang.*; // therefore, the th1 thread also gets the
priority 7
public class ThreadPriorityExample1 extends
Thread
{
public void run()
{
System.out.println("Inside the run() method");
}
System.out.println(currentThread().getName(
));
System.out.println(currentThread().getPriority
());
}
public static void main(String args[])
{ currentThread().setPriority(7);
Main t1=new Main();
Main t2=new Main();
//currentThread().setPriority(7);
t1.start();
t2.start();
//currentThread().setPriority(8);
System.out.println(currentThread().getName(
));
System.out.println(currentThread().getPriority
());
}}
O/P:
Thread-0
7
main
7
Thread-1
7
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.
import java.lang.*;
public class IllegalArgumentException extends Thread
{
public static void main(String argvs[])
{
Thread.currentThread().setPriority(17);
System.out.println("Priority of the main thread is : " +
Thread.currentThread().getPriority());
}
}
O/P:
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
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.
The java.lang.Thread class provides two methods for java daemon thread.
1) public void setDaemon(boolean status): is used to mark the current thread as daemon
thread or user thread.
Syntax:
synchronized (object reference expression)
{
//code block
}
class Table
class MyThread2 extends Thread
{
{
void printTable(int n)
Table t;
{
MyThread2(Table t)
synchronized(this)
{
{
this.t=t;
for(int i=1;i<=5;i++)
}
{
public void run()
System.out.println(n*i);
{
try{
t.printTable(100);
Thread.sleep(400);
}
}catch(Exception e){System.out.println(e);}
}
}}
public class TestSynchronizedBlock1
}//end of the method
{
}
public static void main(String args[])
class MyThread1 extends Thread
{
{
Table obj = new Table();//only one object
Table t;
MyThread1 t1=new MyThread1(obj);
MyThread1(Table t){
MyThread2 t2=new MyThread2(obj);
this.t=t;
t1.start();
}
t2.start();
public void run(){
}
t.printTable(5);
}
}}
O/P:
5
10
15
20
25
100
200
300
400
500
Static Synchronization
If you make any static method as synchronized, the lock will be on the class not on
object.
1
2
3
4
5
6
7
8
9
10
10
20
30
40
50
60
70
80
90
100
100
200
300
400
500
600
700
800
900
1000
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
class Table Thread t3=new Thread()
{ {
synchronized static void printTable(int n) public void run()
{ {
for(int i=1;i<=10;i++){ Table.printTable(100);
System.out.println(n*i); }
try{ };
Thread.sleep(400); Thread t4=new Thread(){
}catch(Exception e){} public void run(){
}}} Table.printTable(1000);
public class TestSynchronization5 }
{ };
public static void main(String[] args) t1.start();
{ t2.start();
Thread t1=new Thread(){ t3.start();
public void run(){ t4.start();
Table.printTable(1); }
} }
};
Thread t2=new Thread(){
public void run(){
Table.printTable(10);
}
};
Deadlock
Deadlock can occur in a situation when a thread is waiting for an object lock, that is
acquired by another thread and second thread is waiting for an object lock that is
acquired by first thread. Since, both threads are waiting for each other to release
the lock, the condition is called deadlock.
public class TestDeadlockExample1
// t2 tries to lock resource2 then resource1
{
Thread t2 = new Thread() {
public static void main(String[] args)
public void run() {
{
synchronized (resource2) {
final String resource1 = "raman";
System.out.println("Thread 2: locked
final String resource2 = “chaman";
resource 2");
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread()
try { Thread.sleep(100);} catch
{
(Exception e) {}
public void run() {
synchronized (resource1) {
synchronized (resource1) {
System.out.println("Thread 1: locked
System.out.println("Thread 2:
resource 1");
locked resource 1");
}
try { Thread.sleep(100);}
}
catch (Exception e) {}
}
};
synchronized (resource2) {
System.out.println("Thread 1: locked
resource 2");
t1.start();
}
t2.start();
}
}
}
}
};
Output:
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
} }}}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
} Output
} Thread 1: Holding lock 1...
} Thread 2: Holding lock 2...
Thread 1: Waiting for lock 2...
Thread 2: Waiting for lock 1...
The above program will hang forever because neither of the threads in position to
proceed and waiting for each other to release the lock, so you can come out of the
program by pressing CTRL+C.
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object(); Solution
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
} }}}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1...");
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
} Output So just changing the order of the locks
Thread 1: Holding lock 1... prevent the program in going into a
Thread 1: Waiting for lock 2... deadlock situation and completes with the
Thread 1: Holding lock 1 & 2... displayed result
Thread 2: Holding lock 1...
Thread 2: Waiting for lock 2...
Thread 2: Holding lock 1 & 2...
Deadlocks cannot be completely resolved. But we can avoid
them by following basic rules mentioned below:
•wait(): The wait() method causes current thread to release the lock and wait until
either another thread invokes the notify() method or the notifyAll() method for this
object, or a specified amount of time has elapsed.
•notify(): The notify() method wakes up a single thread that is waiting on this
object's monitor. If any threads are waiting on this object, one of them is chosen
to be awakened. The choice is arbitrary and occurs at the discretion of the
implementation.
•notifyAll(): Wakes up all threads that are waiting on this object's monitor.
Syntax: Syntax:
public final void notifyAll() public final void notify()
Process of inter-thread communication