[Go to site: main page, start]

0% found this document useful (0 votes)
8 views33 pages

Java Exception Handling & Multithreading Guide

This document covers key concepts in Java programming, focusing on Exception Handling, Multithreaded Programming, and Garbage Collection. It explains the use of try-catch blocks for handling exceptions, the lifecycle and methods of threads, and the importance of synchronization in multithreading. Additionally, it discusses the differences between multiprocessing and multithreading, along with the advantages and disadvantages of multithreading in Java.

Uploaded by

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

Java Exception Handling & Multithreading Guide

This document covers key concepts in Java programming, focusing on Exception Handling, Multithreaded Programming, and Garbage Collection. It explains the use of try-catch blocks for handling exceptions, the lifecycle and methods of threads, and the importance of synchronization in multithreading. Additionally, it discusses the differences between multiprocessing and multithreading, along with the advantages and disadvantages of multithreading in Java.

Uploaded by

jananippriya18
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Java Programming

UNIT-III
Exception Handling: try – catch - throw - throws –- finally – Built-in exceptions - Creating
own Exception classes - garbage collection, finalise -Multithreaded Programming: Thread
Class - Runnable interface – Synchronization – Using synchronized methods – Using
synchronized statement - Interthread Communication – Deadlock

Exception Handling
An exception in Java is an unpredicted condition that arises during the execution of the code
either at compile-time or at run-time.
All the exceptions are handled by the predefined parent class known
as [Link] in Java. The Throwable class has Exception and Error as its subclass.
Exceptions are recoverable and can be recovered using try-catch blocks or throws keywords.
There are mainly two types of exception in Java:
 Built-in Exception
 User Defined Exception

Java Exceptions - Try...Catch


Java Exceptions
When executing Java code, different errors can occur: coding errors made by the
programmer, errors due to wrong input, or other unforeseeable things.
When an error occurs, Java will normally stop and generate an error message. The technical
term for this is: Java will throw an exception (throw an error).

Java try and catch


The try statement allows you to define a block of code to be tested for errors while it is being
executed.
The catch statement allows you to define a block of code to be executed, if an error occurs in
the try block.
The try and catch keywords come in pairs:
Syntax
try {
// Block of code to try
}
catch(Exception e) {
// Block of code to handle errors
}

Example
public class Main {
public static void main(String[ ] args) {
try {
int[] myNumbers = {1, 2, 3};
[Link](myNumbers[10]);
} catch (Exception e) {
[Link]("Something went wrong.");
}
}
}
Finally
The finally statement lets you execute code, after try...catch, regardless of the result:
Example
public class Main {
public static void main(String[] args) {
try {
int[] myNumbers = {1, 2, 3};
[Link](myNumbers[10]);
} catch (Exception e) {
[Link]("Something went wrong.");
} finally {
[Link]("The 'try catch' is finished.");
}
}
}

The output will be:


Something went wrong.

The throw keyword


The throw statement allows you to create a custom error.
The throw statement is used together with an exception type. There are many exception types
available in
Java: ArithmeticException, FileNotFoundException, ArrayIndexOutOfBoundsException, Sec
urityException, etc:

Example
Throw an exception if age is below 18 (print "Access denied"). If age is 18 or older, print
"Access granted":
public class Main {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
}
else {
[Link]("Access granted - You are old enough!");
}
}

public static void main(String[] args) {


checkAge(15); // Set age to 15 (which is below 18...)
}
}

The output will be:


Exception in thread "main" [Link]: Access denied - You must be at
least 18 years old.
at [Link]([Link])
at [Link]([Link])

Java Built-in Exceptions


Built-in Exceptions are those exceptions that are pre-defined in Java Libraries. These are the
most frequently occurring Exceptions. An example of a built-in exception can be
ArithmeticException; it is a pre-defined exception in the Exception class of [Link]
package. These can be further divided into two types:
1. Checked Exception
2. Unchecked Exception
[Link] Exceptions:

Checked exceptions are caught at compile time, indicating potentially recoverable errors.
The compiler enforces handling them before runtime.

For instance, accessing a missing file like "[Link]" can throw a FileNotFoundException,
which can be handled using the throws keyword to specify potential exceptions at compile
time.
Class Not Found Exception
The ClassNotFoundException occurs when the Java Virtual Machine cannot locate a required
class, typically triggered by functions like [Link]() or [Link]().
Code:
public class classNotFound
{
static String classname = "missingClass";
public static void main() throws ClassNotFoundException
{
[Link](classname);
}
}
Output:
[Link]: missingClass

Compile Time Exception:


The possible exception of type [Link] needs to be handled.
Explanation: Since opening the file can cause IOExceptions, the compiler gives a compile-
time exception, and the code is not compiled.

[Link] Exceptions
An Unchecked Exception is an exception that occurs during runtime, often due to logical
errors or improper usage of functions. These exceptions, also known as Runtime Exceptions,

Arithmetic Exceptions
An ArithmeticException is thrown when the code does the wrong arithmetic or mathematical
operation while executing. Divide by 0 is the most common type of wrong mathematical
operation.
Code:
class arithmeticException
{
public static void main()
{
int a = 10, b = 0;
int c = a / b;
}
Output:
[Link]: / by zero
Explanation: Since we are trying to divide 10 by 0, we are causing a mathematical error.
This is predefined in the ArithmeticException of Exception class in Java. Hence, the code is
throwing the exception.

Garbage Collection in Java


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.
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.
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:
protected void finalize(){}

Simple Example of garbage collection in java


public class TestGarbage1{
public void finalize(){[Link]("object is garbage collected");}
public static void main(String args[]){
TestGarbage1 s1=new TestGarbage1();
TestGarbage1 s2=new TestGarbage1();
s1=null;
s2=null;
[Link]();
}
}

OUTPUT:
object is garbage collected
object is garbage collected

Multithreading in Java
Multithreading in Java is an act of executing a complex process using virtual processing
entities independent of each other. These entities are called threads.
Threads in Java are virtual and share the same memory location of the process. As the
threads are virtual, they exhibit a safer way of executing a process.
What are Multitasking and the Types of Multitasking?
Multitasking is an approach to minimize execution time and maximize CPU utilization by
executing multiple tasks simultaneously. You can achieve the process of multitasking in Java
using two methods, as described below.

Multiprocessing in Java
Multiprocessing in Java is purely based on the number of processors available on the host
computer. Every process initiated by the user is sent to the CPU (processor). It loads the
registers on the CPU with the data related to the assigned process.
Multithreading in Java
Multithreading in Java is a similar approach to multiprocessing. However, there are some
fundamental differences between the two. Instead of a physical processor, multithreading
involves virtual and independent threads.
It assigns each process with one or more threads based on their complexity. Each thread is
virtual and independent of the other. This makes process execution much safer. If a thread or
two are terminated during an unexpected situation, the process execution will not halt.
What is a Thread in Java?
A thread is the smallest segment of an entire process. A thread is an independent, virtual and
sequential control flow within a process. In process execution, it involves a collection
of threads, and each thread shares the same memory. Each thread performs the job
independently of another thread.

Lifecycle of a Thread in Java


The lifecycle of each thread in Java has five different stages. You will look into each one of
those stages in detail. The Stages of the Lifecycle are mentioned below.
 New
 Runnable
 Running
 Waiting
 Dead
New
The first stage is "New". This stage is where it initiates the thread. After that, every thread
remains in the new state until the thread gets assigned to a new task.
Runnable
The next stage is the runnable stage. Here, a thread gets assigned to the task and sets itself for
running the task.
Running
The third stage is the execution stage. Here, the thread gets triggered as control enters the
thread, and the thread performs a task and continues the execution until it finishes the job.
Waiting
At times, there is a possibility that one process as a whole might depend on another. During
such an encounter, the thread might halt for an intermediate result because of its dependency
on a different process. This stage is called the Waiting Stage.
Dead
The final stage of the process execution with Multithreading in Java is thread termination.
After it terminates the process, the JVM automatically declares the thread dead and
terminates the thread. This stage is known as the dead thread stage.

Methods of Multithreading in Java


Following are the methods for Multithreading in Java.

The start method initiates the


start()
execution of a thread
The currentThread method returns
currentThread() the reference to the currently
executing thread object.

The run method triggers an action


run()
for the thread

The isAlive method is invoked to


isAlive()
verify if the thread is alive or dead

The sleep method is used to suspend


sleep()
the thread temporarily

The yield method is used to send


the currently executing threads to
yield()
standby mode and runs different
sets of threads on higher priority

The suspend method is used to


suspend() instantly suspend the thread
execution

The resume method is used to


resume() resume the execution of a
suspended thread only

The interrupt method triggers an


interrupt() interruption to the currently
executing thread class

The destroy method is invoked to


destroy() destroy the execution of a group of
threads
The stop method is used to stop the
stop()
execution of a thread

After the methods of Multithreading in Java, you will go through an example based on
Multithreading in Java.
Example for Multithreading in Java
The following is an example based on multithreading in Java using the runnable interface.
//Code
package multithreading;
class ThreadCount extends Thread{
ThreadCount(){
super("Overriding Thread Class");
[Link]("New thread created" + this);
start();
}
public void run(){ //Run Method
try{
for (int i=0 ;i<10;i++){
[Link]("New thread created" + this);
[Link](1500);
}
}
catch(InterruptedException e){
[Link]("Currently executing thread is interrupted");
}
[Link]("Currently executing thread run is terminated" );
}
}
public class MultiThreading{
public static void main(String args[]){
ThreadCount C = new ThreadCount();
try{
while([Link]()){
[Link]("Main Method Thread will be alive, until it's Child Thread stays alive");
[Link](2500); //Sleep method
}
}
catch(InterruptedException e){
[Link]("Main Method thread is interrupted");
}
[Link]("Main Method's thread run is terminated" );
}
}
//Output:
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
New thread createdThread[Overriding Thread Class,5,main]
Main Method Thread will be alive, until it's Child Thread stays alive
Currently executing thread run is terminated
Main Method's thread run is terminated

Multiprocessing vs. Multithreading in Java


The following table explains the fundamental differences between Multiprocessing and
Multithreading in Java

Multiprocessing Multithreading

Multithreading in Java requires


Multiprocessing requires multiple physical processors for
virtual threads. These threads are
executing a complex process.
independent of each other.

Multiprocessing involves two types, namely symmetric and There are no different types of
asymmetric multiprocessing. multithreading in Java

Multithreading in Java is
Multiprocessing is heavy and time-consuming completely light and a timesaving
procedure

In the process of Multithreading in


In multiprocessing, each process owns a separate memory
Java, Threads share the same
location
memory location

Since all the threads are


independent of each other, if any
If one processor is compromised, then the respective process
thread is compromised, then the
of that CPU or the entire process may collapse
entire process will not be affected
by any means.

Advantages of Multithreading in Java


Mentioned below are the few advantages of Multithreading in Java:
 Multithreading in Java improves the performance and reliability
 Multithreading in Java minimizes the execution period drastically
 There is a smooth and hassle-free GUI response while using Multithreading in Java
 The software maintenance cost is lower
 The CPU and other processing resources are modes judiciously used
Disadvantages of Multithreading in Java
Following are a few disadvantages of Multithreading in Java:
 Multithreading in Java poses complexity in code debugging
 Multithreading in Java increases the probability of a deadlock in process execution
 The results might be unpredictable in some worst-case scenarios
 Complications might occur while code is being ported

Synchronization in Java
Synchronization in java is the capability to control the access of multiple threads to any
shared resource. In the Multithreading concept, multiple threads try to access the
shared resources at a time to produce inconsistent results. The synchronization is
necessary for reliable communication between threads.
Why we use Synchronization
 Synchronization helps in preventing thread interference.
 Synchronization helps to prevent concurrency problems.
Types of Synchronization
Synchronization is classified into two types
 Process Synchronization
 Thread Synchronization
Process Synchronization:
 The process is nothing but a program under execution. It runs independently
isolated from another process. The resources like memory and CPU time, etc. are
allocated to the process by the operation System.
Thread Synchronization:
Thread synchronization is two types, they are:
[Link] Exclusive:
A Mutex or Mutual Exclusive helps only one thread to access the shared resources. It
won’t allow the accessing of shared resources at a time. It can be achieved in the
following ways.
 Synchronized Method
 Synchronized block
 Static Synchronization
2. Cooperation (Inter Thread Communication in java)
Lock Concept in Java
 Synchronization Mechanism developed by using the synchronized keyword in
java language. It is built on top of the locking mechanism, this locking
mechanism is taken care of by Java Virtual Machine (JVM). The synchronized
keyword is only applicable for methods and blocks, it can’t apply to classes and
variables. Synchronized keyword in java creates a block of code is known as a
critical section. To enter into the critical section thread needs to obtain the
corresponding object’s lock.

Java Synchronized Method


If we use the Synchronized keywords in any method then that method is Synchronized
Method.
 It is used to lock an object for any shared resources.
 The object gets the lock when the synchronized method is called.
 The lock won’t be released until the thread completes its function.
Syntax:
1Acess_modifiers synchronized return_type method_name (Method_Parameters) {
2// Code of the Method.
3}
Java Synchronized Method Example:
1 class Power{
2 synchronized void printPower(int n){//method synchronized
3 int temp = 1;
4 for(int i=1;i<=5;i++){
5 [Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
6 temp = n*temp;
7 try{
8 [Link](500);
9 }catch(Exception e){[Link](e);}
10 }
11 }
12 }
13 class Thread1 extends Thread{
14 Power p;
15 Thread1(Power p){
16 this.p=p;
17 }
18 public void run(){
19 [Link](5);
20 }
21 }
22 class Thread2 extends Thread{
23 Power p;
24 Thread2(Power p){
25 this.p=p;
26 }
27 public void run(){
28 [Link](8);
29 }
30 }
31 public class Synchronization_Example2{
32 public static void main(String args[]){
33 Power obj = new Power();//only one object
34 Thread1 p1=new Thread1(obj);
35 Thread2 p2=new Thread2(obj);
36 [Link]();
37 [Link]();
38 }
39 }
Output:
1 Thread-0:- 5^1 value: 5
2 Thread-0:- 5^2 value: 25
3 Thread-0:- 5^3 value: 125
4 Thread-0:- 5^4 value: 625
5 Thread-0:- 5^5 value: 3125
6 Thread-1:- 8^1 value: 8
7 Thread-1: - 8^2 value: 64
8 Thread-1:- 8^3 value: 512
9 Thread-1:- 8^4 value: 4096
10 Thread-1:- 8^5 value: 32768
Here we used synchronized keywords. It helps to execute a single thread at a time. It is not
allowing another thread to execute until the first one is completed, after completion of the
first thread it allowed the second thread. Now we can see the output correctly the powers 5
and 8 from n1 to n5. Thread-0 completed then only thread-1 begin.
Synchronized Block
 Suppose you don’t want to synchronize the entire method, you want to synchronize
few lines of code in the method, then a synchronized block helps to synchronize those
few lines of code. It will take the object as a parameter. It will work the same as
Synchronized Method. In the case of synchronized method lock accessed is on the
method but in the case of synchronized block lock accessed is on the object.
Syntax:
1 synchronized (object) {
2 //code of the block.
3 }
4 Program to understand the Synchronized Block:
5 class Power{
6 void printPower(int n){
7 synchronized(this){ //synchronized block
8 int temp = 1;
9 for(int i=1;i<=5;i++){
10 [Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
11 temp = n*temp;
12 try{
13 [Link](500);
14 }catch(Exception e){[Link](e);}
15 }
16 }
17 }
18 }
19
20 class Thread1 extends Thread{
21 Power p;
22 Thread1(Power p){
23 this.p=p;
24 }
25 public void run(){
26 [Link](5);
27 }
28
29 }
30 class Thread2 extends Thread{
31 Power p;
32 Thread2(Power p){
33 this.p=p;
34 }
35 public void run(){
36 [Link](8);
37 }
38 }
39
40 public class Synchronization_Example3{
41 public static void main(String args[]){
42 Power obj = new Power();//only one object
43 Thread1 p1=new Thread1(obj);
44 Thread2 p2=new Thread2(obj);
45 [Link]();
46 [Link]();
47
48 }
49 }
Output:
1 Thread-0:- 5^1 value: 5
2 Thread-0:- 5^2 value: 25
3 Thread-0:- 5^3 value: 125
4 Thread-0:- 5^4 value: 625
5 Thread-0:- 5^5 value: 3125
6 Thread-1:- 8^1 value: 8
7 Thread-1:- 8^2 value: 64
8 Thread-1:- 8^3 value: 512
9 Thread-1:- 8^4 value: 4096
10 Thread-1:- 8^5 value: 32768
In this example, we didn’t synchronize the entire method but we synchronized few lines of
code in the method. We got the results exactly as the synchronized method.
Static Synchronization
 In java, every object has a single lock (monitor) associated with it. The thread which
is entering into synchronized method or synchronized block will get that lock, all
other threads which are remaining to use the shared resources have to wait for the
completion of the first thread and release of the lock.
 Suppose in the case of where we have more than one object, in this case, two separate
threads will acquire the locks and enter into a synchronized block or synchronized
method with a separate lock for each object at the same time. To avoid this, we will
use static synchronization.
 In this, we will place synchronized keywords before the static method. In static
synchronization, lock access is on the class not on object and Method.
Syntax:
1 synchronized static return_type method_name (Parameters) {
2 //code
3 }
4 Or
5 synchronized static return_type method_name (Class_name.class) {
6 //code
7 }
8
9 Program without Static Synchronization:
10class Power{
11 synchronized void printPower(int n){ //static synchronized method
12 int temp = 1;
13 for(int i=1;i<=5;i++){
14 [Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
15 temp = n*temp;
16 try{
17 [Link](400);
18 }catch(Exception e){}
19 }
20
21 }
22}
23class Thread1 extends Thread{
24Power p;
25Thread1(Power p){
26this.p=p;
27}
28public void run(){
[Link](2);
30}
31
32}
33
34class Thread2 extends Thread{
35Power p;
36Thread2(Power p){
37this.p=p;
38}
39public void run(){
[Link](3);
41}
42}
43
44class Thread3 extends Thread{
45Power p;
46Thread3(Power p){
47this.p=p;
48}
49public void run(){
[Link](5);
51}
52}
53
54class Thread4 extends Thread{
55Power p;
56Thread4(Power p){
57this.p=p;
58}
59public void run(){
[Link](8);
61}
62}
63
64public class Synchronization_Example4{
65public static void main(String args[]){
66Power ob1 = new Power(); //first object
67Power ob2 = new Power(); //second object
68Thread1 p1 = new Thread1(ob1);
69Thread2 p2 = new Thread2(ob1);
70Thread3 p3 = new Thread3(ob2);
71Thread4 p4 = new Thread4(ob2);
72
[Link]();
[Link]();
[Link]();
[Link]();
77}
78}
Output:
1 Thread-2:- 5^1 value: 5
2 Thread-0:- 2^1 value: 2
3 Thread-2:- 5^2 value: 25
4 Thread-0:- 2^2 value: 4
5 Thread-2:- 5^3 value: 125
6 Thread-0:- 2^3 value: 8
7 Thread-2:- 5^4 value: 625
8 Thread-0:- 2^4 value: 16
9 Thread-2: - 5^5 value: 3125
10 Thread-0: - 2^5 value: 32
11 Thread-3:- 8^1 value: 8
12 Thread-1:- 3^1 value: 3
13 Thread-3:- 8^2 value: 64
14 Thread-1:- 3^2 value: 9
15 Thread-3:- 8^3 value: 512
16 Thread-1:- 3^3 value: 27
17 Thread-3:- 8^4 value: 4096
18 Thread-1:- 3^4 value: 81
19 Thread-3:- 8^5 value: 32768
20 Thread-1:- 3^5 value: 243
If you observe the above results Thread-0, Thread-1 belongs to object-1 and Thread-2,
Thread-3 are belonging to Object-2. So, there is no interference between thread 0 and 1
because of the same object (obj1). In the same way, there is no interference between Thread 2
and 3 because they belong to the same object (obj2). But if you observe there is interference
between Thread 0 and 2, same as there is interference between Thread 1 and 3. To rectify this
problem we will use static synchronization.
Program with static synchronization:
1 class Power{
2 synchronized static void printPower(int n){ //static synchronized method
3 int temp = 1;
4 for(int i=1;i<=5;i++){
5 [Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
6 temp = n*temp;
7 try{
8 [Link](400);
9 }catch(Exception e){}
10 }
11
12 }
13}
14class Thread1 extends Thread{
15Power p;
16Thread1(Power p){
17this.p=p;
18}
19public void run(){
[Link](2);
21}
22
23}
24
25class Thread2 extends Thread{
26Power p;
27Thread2(Power p){
28this.p=p;
29}
30public void run(){
[Link](3);
32}
33}
34
35class Thread3 extends Thread{
36Power p;
37Thread3(Power p){
38this.p=p;
39}
40public void run(){
[Link](5);
42}
43}
44
45class Thread4 extends Thread{
46Power p;
47Thread4(Power p){
48this.p=p;
49}
50public void run(){
[Link](8);
52}
53}
54
55public class Synchronization_Example4{
56public static void main(String args[]){
57Power ob1 = new Power(); //first object
58Power ob2 = new Power(); //second object
59Thread1 p1 = new Thread1(ob1);
60Thread2 p2 = new Thread2(ob1);
61Thread3 p3 = new Thread3(ob2);
62Thread4 p4 = new Thread4(ob2);
63
[Link]();
[Link]();
[Link]();
[Link]();
68}
69}
Output:
1 Thread-0:- 2^1 value: 2
2 Thread-0:- 2^2 value: 4
3 Thread-0:- 2^3 value: 8
4 Thread-0:- 2^4 value: 16
5 Thread-0:- 2^5 value: 32
6 Thread-1:- 3^1 value: 3
7 Thread-1:- 3^2 value: 9
8 Thread-1:- 3^3 value: 27
9 Thread-1:- 3^4 value: 81
10 Thread-1:- 3^5 value: 243
11 Thread-2:- 5^1 value: 5
12 Thread-2:- 5^2 value: 25
13 Thread-2:- 5^3 value: 125
14 Thread-2:- 5^4 value: 625
15 Thread-2:- 5^5 value: 3125
16 Thread-3:- 8^1 value: 8
17 Thread-3:- 8^2 value: 64
18 Thread-3:- 8^3 value: 512
19 Thread-3:- 8^4 value: 4096
20 Thread-3:- 8^5 value: 32768
In this static synchronization, we can observe there is no interference between Thread-0 and
Thread-2 same as there is no interference between Thread-1 and 3. The next thread is
executing after the previous thread completion or releasing lock only.
Inter – Thread Communication
Inter – Thread communication or cooperation is a communication of two or more threads
with each other. It can be done by using the following methods.
 wait()
 notify()
 notifyAll()
Why we need Inter – Thread Communication?
 There is a situation on the thread that keeps on checking some conditions repeatedly,
once that condition satisfies thread moves with the appropriate action. This situation
is known as polling. This is a wastage of CPU time, to reduce the wastage of CPU
time due to polling, java uses Inter – Thread Communication Mechanism.
 wait(), notify(), notifyAll() methods must be called within a synchronized method or
block otherwise program will compile but when you run it, it will throw illegal
monitor State Exception.
Example:
1 class Power{
2 void printPower(int n){
3 int temp = 1;
4 for(int i=1;i<=5;i++){
5 [Link]([Link]().getName() + ":- " +n + "^"+ i + " value: " + n*temp);
6 temp = n*temp;
7 try{
8 [Link](); //wait placed outside of the synchronized block or method
9 [Link](500);
10 }catch(Exception e){[Link](e);}
11 }
12
13 }
14}
Output:
1 Thread-0:- 5^1 value: 5
2 [Link]
3 Thread-0:- 5^2 value: 25
4 [Link]
5 Thread-0:- 5^3 value: 125
6 [Link]
7 Thread-0:- 5^4 value: 625
8 [Link]
9 Thread-0:- 5^5 value: 3125
10 [Link]
11 Thread-1:- 8^1 value: 8
12 [Link]
13 Thread-1:- 8^2 value: 64
14 [Link]
15 Thread-1:- 8^3 value: 512
16 [Link]
17 Thread-1:- 8^4 value: 4096
18 [Link]
19 Thread-1:- 8^5 value: 32768
20 [Link]
1. wait () Method
 It causes the current thread to place itself into the waiting stage until another thread
invokes the notify() method or notifyAll() method for this object.
2. notify () Method
 This method wakes up a single thread called wait () on the same object. If there is
more than one thread that is waiting on this same object, then any one of them
arbitrarily chosen to be awakened. Here awakened thread will not able to proceed
until the current thread release lock. If any threads are trying to get the lock on this
object then the awakened thread will also compete with them in the usual manner.
Syntax:
public final void notify()
3. notify All() Method
 Rather than a single thread, it will wake up all the threads waiting on this object
monitor. The awakened thread will not able to proceed until the current thread
releases the lock. Again, these awakened threads need to compete with all other
threads which are trying to get the lock on this object.
Syntax:
public final void notifyAll()

Deadlock in Java Multithreading


Deadlock occurs in Java when multiple threads block each other while waiting for locks held
by one another. To prevent deadlocks, we can use the synchronized keyword to make
methods or blocks thread-safe which means only one thread can have the lock of the
synchronized method and use it, other threads have to wait till the lock releases other one
acquires the lock.
Example: Below is a simple example demonstrating a deadlock condition in Java.
// Utility class to pause thread execution
class Util {
static void sleep(long millis)
{
try {
[Link](millis);
}
catch (InterruptedException e) {
[Link]();
}
}
}
// this class is shared by both threads
class Shared {

// first synchronized method


synchronized void test1(Shared s2)
{
[Link]([Link]().getName()
+ " enters test1 of " + this);
[Link](1000);

// Trying to call test2 on another object


s2.test2();
[Link]([Link]().getName()
+ " exits test1 of " + this);
}

// Second synchronized method


synchronized void test2()
{
[Link]([Link]().getName()
+ " enters test2 of " + this);
[Link](1000);

// taking object lock of s1 enters into test1 method


[Link]([Link]().getName()
+ " exits test2 of " + this);
}
}

class Thread1 extends Thread {


private Shared s1;
private Shared s2;

// constructor to initialize fields


public Thread1(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}

// run method to start a thread


@Override public void run() { s1.test1(s2); }
}

class Thread2 extends Thread {


private Shared s1;
private Shared s2;

// constructor to initialize fields


public Thread2(Shared s1, Shared s2)
{
this.s1 = s1;
this.s2 = s2;
}

// run method to start a thread


@Override public void run() { s2.test1(s1); }
}
public class Geeks {

// In this class deadlock occurs


public static void main(String[] args)
{
// creating one object
Shared s1 = new Shared();
Shared s2 = new Shared();

// creating first thread and starting it


Thread1 t1 = new Thread1(s1, s2);
[Link]("Thread1");
[Link]();

// creating second thread and starting it


Thread2 t2 = new Thread2(s1, s2);
[Link]("Thread2");
[Link]();
[Link](2000);
}
}
Output:

Output
Note: It is not recommended to run the program in an online IDE. We can run the above
source code locally, but it gets stuck in a deadlock, preventing execution.
Explanation:
 Thread t1 starts by acquiring a lock on the s1 and enters the test1() method of s1.
 Thread t2 starts by acquiring a lock on the s2 and enters the test1() method of s2.
 In the test1() method both threads try to acquire locks on each other's objects but the
locks are already held by the other thread causing both threads to wait indefinitely for
the other to release the lock.
 Neither test1() nor test2() methods complete execution and the program remains stuck
in the deadlock state.
Locks in Java
Below is the diagrammatic representation of how Locks work and prevent Deadlock
conditions.

Detectecting Deadlocks
We can detect deadlocks in a running Java program using the following steps:
1. List the active Java processes:
jps -l
Response:

Response
This will list the running Java processes and also mention that there is a deadlock if we want
to generate a thread dump.
2. Identify the process ID (PID) of the target program and run:
jcmd <PID> [Link] // replace PID with the process ID
Replace <PID> with the process ID from the list provided by jps -l. This command outputs
the state of the threads, which you can then analyze for deadlocks.
After running the above two commands, we can see deadlock occurs:
As we can see it is mentioned that found 1 deadlock.
Preventing Deadlocks
We can avoid deadlock conditions by knowing its possibilities. It's a very complex process
and not easy to catch. Still, if we try, we can avoid this. There are some methods by which we
can avoid this condition. We can't completely remove its possibility but we can reduce it.
 Avoid Nested Locks: This is the main reason for deadlock. Mainly happens when we
give locks to multiple threads. Avoid giving lock to multiple threads if we already
have given to one.
 Avoid Unnecessary Locks: We should have lock only those members who are
required. Having a lock on unnecessarily can lead to deadlock.
 Using thread join: Deadlock condition appears when one thread is waiting for the
other to finish. If this condition occurs we can use Thread. Join the with the maximum
time you think the execution will take.

You might also like