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

UNIT 3-Exception Handling and MultiThreading

Uploaded by

rsnaveen2323
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
77 views

UNIT 3-Exception Handling and MultiThreading

Uploaded by

rsnaveen2323
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 54

RAMCO INSTITUTE OF TECHNOLOGY

Department of Information Technology


Academic Year: 2023 – 2024 (Odd Semester)

CS3391 & Object-Oriented Programming

Unit III – INHERITANCE, PACKAGES AND INTERFACES 9

Exception Handling basics- Multiple catch Clauses-Nested try Statements- Java’s Built-in Exceptions-
User defined Exception. Multithreaded Programming: Java Thread Model-Creating a Thread and
Multiple Threads – Priorities – Synchronization- Inter Thread Communication- Suspending- Resuming,
and Stopping Threads-Multithreading. Wrappers-Auto boxing.

Exception Handling basics

Exception Handling is a mechanism to handle the runtime errors so that the normal flow of the
application can be maintained.

Exception: is an abnormal event that arises during the execution of the program and disrupts
the normal flow of the program. For example, if a user is trying to divide an integer by 0 then it is an
exception, as it is not possible mathematically.

There are various types of interruptions while executing any program like errors, exceptions,
and bugs. These interruptions can be due to programming mistakes or due to system issues.
Depending on the conditions they can be classified as exceptions and errors.

1.Exception:

➢ Exceptions are unwanted conditions that disrupt the flow of the program.
➢ Exceptions usually occur due to the code and can be recovered.
➢ Exceptions can be of both checked (exceptions that are checked by the compiler) and
unchecked (exceptions that cannot be checked by the compiler) type.
➢ They can occur at both compile time and ruin time.
➢ In Java, exceptions belong to java.lang.Exception class.

2.Error:

➢ An error is also an unwanted condition but it is caused due to lack of resources and
indicates a serious problem.
➢ Errors are irrecoverable, they cannot be handled by the programmers.
➢ Errors are of unchecked type only.
➢ They can occur only at run time.
➢ In java, errors belong to java.lang.Error class. Eg: OutOfMemoryError.

Need of Handling Exception

if there is a program with some lines of code and an exception occurs a mid-way after
executing certain lines of code, in this case, the execution terminates abruptly.

But if the programmer handles the exceptions explicitly, all the statements of code are
executed properly and the flow of the program is maintained.

For Example: Problem without Exception Handling

class SampleCode

public static void main(String args[])

System.out.println("Hello World!");

int a = 10;

int b = 0;

System.out.println(a / b);

System.out.println("Welcome to java programming.");

System.out.println("Bye.")

Output:
Hello World!
Exception in thread "main" java.lang.ArithmeticException: / by zero
at SampleException.main(SampleException.java:8)
In the above code, the first three lines in the main method are executed properly. At the 8th
line, an integer is divided by 0, which is not possible and an exception is raised by JVM (Java Virtual
Machine). In this case, the exception is not handled by the programmer which will halt the program in
between by throwing the exception, and the rest of the lines of code won't be executed.

Solution by Exception Handling:

Now, the above program is provided with try-catch statement to handle the exception.

class SampleCode

public static void main(String args[])

System.out.println("Hello World!");

int a = 10;

int b = 0;

try

System.out.println(a / b); // code that may rise exception

catch( ArithmeticException e)

System.out.println(e);

// rest code of the program

System.out.println("Welcome to java programming.");

System.out.println("Bye.")

}
Output:

Exception in thread "main" java.lang.ArithmeticException: / by zero

Welcome to java programming

Bye

Now the exception is handled using try cath block and the flow of the code sequence is maintained.
Hence the remaining statements is also printed.

The JVM firstly checks whether the exception is handled or not. If exception is not handled, JVM
provides a default exception handler that performs the following tasks:

o Prints out exception description.


o Prints the stack trace (Hierarchy of methods where the exception occurred).
o Causes the program to terminate.

But if the application programmer handles the exception, the normal flow of the application is
maintained, i.e., rest of the code is executed.
Exception Hierarchy

The java.lang.Throwable class is the root class of Java Exception hierarchy inherited by two subclasses:
Exception and Error. The hierarchy of Java Exception classes is given below:

Types of Java Exceptions

There are mainly two types of exceptions: checked and unchecked. An error is considered as
the unchecked exception. However, according to Oracle, there are three types of exceptions namely:

1. Checked Exception
2. Unchecked Exception
3. Error

1) Checked Exception

➢ Checked exceptions are those exceptions that are checked at compile time by the
compiler.
➢ The program will not compile if they are not handled.
➢ These exceptions are child classes of the Exception class.
➢ IOException, ClassNotFoundException, InvocationTargetException, and SQL Exception are a
few of the checked exceptions in Java.
2) Unchecked Exception

➢ Unchecked exceptions are those exceptions that are checked at run time by JVM, as the
compiler cannot check unchecked exceptions,
➢ The programs with unchecked exceptions get compiled successfully but they give runtime
errors if not handled.
➢ These are child classes of Runtime Exception Class.
➢ ArithmeticException, NullPointerException, NumberFormatException,
IndexOutOfBoundException are a few of the unchecked exceptions in Java.

3) Error

Error is irrecoverable. Some example of errors are OutOfMemoryError, VirtualMachineError,


AssertionError etc.

Difference between Checked and UnChecked Exception

Checked Exception Unchecked Exception


Occur at compile time. Occur at runtime.
The compiler does not check for unchecked
The compiler checks for checked exceptions.
exceptions.
If checked exceptions are not handled we get a If unchecked exceptions are not handled
compile-time error. we get a run time error.
Can be handled at compile time. Can not be caught/handled at runtime.
They are direct subclasses of exception class but do They are subclasses of the Runtime
not inherit Runtime Exception Class. Exception class.
Eg: ArithmeticException,
NullPointerException,
Eg: IOException, ClassNotFoundException, NumberFormatException,
SQLException are common checked exceptions. StringIndexOutOfBoundException,
ArrayIndexOutOfBound Exception are
common unchecked exceptions.

Java Exception Keywords:

Java exception handling is managed via five keywords: try, catch, throw, throws, and finally

• Try block : contains the program statements that may raise an exception. The try block must
be followed by either catch or finally.
• Catch block: is used to handle the raised exception. It must be preceded by try block and can
be followed by finally block later.
• Throw keyword is used to explicitly throw an exception.
• Throws keyword is used to declare an exception. It specifies that there may occur an
exception in the method. It doesn't throw an exception. It is always used with method
signature.
• Finally block contains statements that must be executed after the try block. Finally block code
is executed whether an exception is handled or not. Finally block is used to execute important
statements such as closing statement, release the resources, and release memory also.

Java try-catch block:

Java try block is used to enclose the code that might throw an exception.

Syntax: of try-catch

try
{
// code that may throw an exception
}
catch(Exception_class_Name ref)
{

Syntax: of try-finally

try
{
// code that may throw an exception
}
finally
{

Java Catch block:

Java catch block is used to handle the Exception by declaring the type of exception within the
parameter. The declared exception must be the parent class exception ( i.e., Exception) or the
generated exception type. However, the good approach is to declare the generated type of exception.
Multiple Catch Clauses:
A try block can be followed by one or more catch blocks. Each catch block must contain a
different exception handler. Hence multi-catch block is used to perform different tasks at the
occurrence of different exceptions.

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.

Example Program 1: Multiple Catch Block


public class MultipleCatchBlock1 {
public static void main(String[] args) {
try{
int a[]=new int[5];
a[5]=30/0;
}
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");
}
System.out.println("rest of the code");
}
}
Output:
Arithmetic Exception Occurs
rest of the code

Example Program 2: Multiple Catch Block

public class MultipleCatchBlock2


{
public static void main(String[] args)
{
try
{
int a[]=new int[5];
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");
}
System.out.println("rest of the code");
}
}

Output:
ArrayIndexOutOfBounds Exception occurs
rest of the code

Example Program 3: Multiple Catch Block


public class MultipleCatchBlock3 {

public static void main(String[] args) {

try{
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");
}
System.out.println("rest of the code");
}
}
Output:
Parent Exception Occurs
rest of the code
In this Program, NullPointerException is generated but the corresponding exception type is
not provided. In such case, the catch block containing the parent exception class Exception will be
invoked.

Nested try Statements:


In Java, using a try block inside another try block is permitted. It is called as nested try block.
For example, the inner try block can be used to handle ArrayIndexOutOfBoundsException while
the outer try block can handle the ArithemeticException (division by zero).

Syntax:
....
//main try block
try
{
statement 1;
statement 2;
//try catch block within another try block
try
{
statement 3;
statement 4;
//try catch block within nested try block
try
{
statement 5;
statement 6;
}
catch(Exception e2)
{
//exception message
}
}
catch(Exception e1)
{
//exception message
}
}
//catch block of parent (outer) try block
catch(Exception e3)
{
//exception message
}
....

Example Program: Nested Try Statements


public class NestedTryBlock{
public static void main(String args[]){
//outer try block
try{
//inner try block 1
try{
System.out.println("going to divide by 0");
int b =39/0;
}
//catch block of inner try block 1
catch(ArithmeticException e)
{
System.out.println(e);
}

//inner try block 2


try{
int a[]=new int[5];
//assigning the value out of array bounds
a[5]=4;
}
//catch block of inner try block 2
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
System.out.println("other statement");
}
//catch block of outer try block
catch(Exception e)
{
System.out.println("handled the exception (outer catch)");
}
System.out.println("normal flow..");
}
}

Output:
going to divide by 0
java.lang.ArithmeticException:/by Zero
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 4
other statement
normal flow

Another Example Program:

Let's consider the following example. Here the try block within nested try block (inner try block
2) do not handle the exception. The control is then transferred to its parent try block (inner try block
1). If it does not handle the exception, then the control is transferred to the main try block (outer try
block) where the appropriate catch block handles the exception. It is termed as nesting.
public class NestedTryBlock2 {

public static void main(String args[])

// outer (main) try block

try {

//inner try block 1

try {

// inner try block 2

try {

int arr[] = { 1, 2, 3, 4 };

//printing the array element out of its bounds

System.out.println(arr[10]);

// to handles ArithmeticException

catch (ArithmeticException e) {

System.out.println("Arithmetic exception");

System.out.println(" inner try block 2");

// to handle ArithmeticException

catch (ArithmeticException e) {

System.out.println("Arithmetic exception");

System.out.println("inner try block 1");

}
// to handle ArrayIndexOutOfBoundsException

catch (ArrayIndexOutOfBoundsException e4) {

System.out.print(e4);

System.out.println(" outer (main) try block");

catch (Exception e5) {

System.out.print("Exception");

System.out.println(" handled in main try-block");

Output:

java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 4

outer (main) try block

When any try block does not have a catch block for a particular exception, then the 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, then the Java
runtime system will handle the exception. Then it displays the system generated message for that
exception.
Java’s finally block:

➢ Java finally block is a block used to execute important code such as closing the connection, etc.
➢ Java code within the finally block is always executed whether an exception is handled or not.
Therefore, it contains all the necessary statements that need to be printed regardless of the
exception occurs or not.
➢ The finally block follows the try-catch block.

Use of finally block:


➢ finally block in java can be used to put “clean up code” such as a file, closing connection
etc.

➢ the important statements to be printed can be placed in the finally block.


Case 1: When an exception does not occur

In the following example, the Java program does not throw any exception, and the finally block
is executed after the try block.

class TestFinallyBlock {
public static void main(String args[]){
try{
//below code do not throw any exception
int data=25/5;
System.out.println(data);
}
//catch won't be executed
catch(NullPointerException e){
System.out.println(e);
}
//executed regardless of exception occurred or not
finally {
System.out.println("finally block is always executed");
}
System.out.println("rest of the code...");
}
}
Output:
5
finally block is always executed
rest of the code

Case 2: When an exception occur but not handled by the catch block

Here, the code throws an exception however the catch block cannot handle it. Despite this, the
finally block is executed after the try block and then the program terminates abnormally.
public class TestFinallyBlock1{
public static void main(String args[]){

try {

System.out.println("Inside the try block");

//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);
}

//executes regardless of exception occured or not


finally {
System.out.println("finally block is always executed");
}

System.out.println("rest of the code...");


}
}
Output:
Inside the try block
finally block is always executed
Exception in thread ‘main’ java.lang.ArithmeticException: / by zero at
TestFinallyBlock1.main(TestFinallyBlock1.java:9)
Case 3: When an exception occurs and is handled by the catch block

In the following example, the Java program throws an exception and the catch block handles
the exception. Later the finally block is executed after the try-catch block. Further, the rest of the code
is also executed normally.

public class TestFinallyBlock2{


public static void main(String args[]){
try {
System.out.println("Inside try block");

//below code throws divide by zero exception


int data=25/0;
System.out.println(data);
}
//handles the Arithmetic Exception / Divide by zero exception
catch(ArithmeticException e){
System.out.println("Exception handled");
System.out.println(e);
}
//executes regardless of exception occured or not
finally {
System.out.println("finally block is always executed");
}
System.out.println("rest of the code...");
}
}
Output:
Inside try block
Exception handled
java.lang.ArithmeticException:/ by zero
finally block is always executed
rest of the code…
Java’s Built-in Exception:

Java’s Built-in exceptions are the exceptions which are available in Java libraries. These exceptions
are suitable to explain certain error situations.

1) Checked Exception
Checked exceptions are also known as compile-time exceptions as these exceptions are
checked by the compiler during the compilation process to confirm whether the exception is
handled by the programmer or not. If not, then the system displays a compilation error.
The classes that directly inherit the Throwable class except RuntimeException and Error are
known as checked exceptions. For example, IOException, SQLException, etc. Checked exceptions
are checked at compile-time.
2) Unchecked Exception
The unchecked exceptions are those exceptions that occur during the execution of the
program. Hence they are also referred to as Runtime exceptions. These exceptions are generally
ignored during the compilation process.
The classes that inherit the RuntimeException are known as unchecked exceptions. For
example, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, etc.
Unchecked exceptions are not checked at compile-time, but they are checked at runtime.

3) Error

Error is irrecoverable. Some example of errors are OutOfMemoryError, VirtualMachineError,


AssertionError etc.

Compile Time Exception: (Checked Exception)


IOException:
The IOException is simply an exception that is thrown when an I/O error occurs. It is also the
base class of such exceptions which occur while reading or accessing files, directories and streams.

There are many subclasses of IOException like FileNotFoundException,


EndOfStreamException, DirectoryNotFoundException etc.

import java.io.*;

// Example of FileNotFoundException
public class Main {

public static void main(String[] args) {


// Creating an instance of FileReader class
FileReader fileReader = new FileReader("Test.txt");

System.out.println(fileReader.read());

fileReader.close();
}
}

Output:
Main.java:8: error: unreported exception FileNotFoundException; must be caught or
declared to be thrown
How to handle IOException in java?
IOException can be handled using try and catch blocks to handle the exception.
import java.io.*;
// Example of FileNotFoundException
public class Main {

public static void main(String[] args) {

try {
// Creating an instance of FileReader class
FileReader fileReader = new FileReader("Test.txt");

System.out.println(fileReader.read());

fileReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}

The above program compiles successfully and does not thrown any exception at compile time.
However, if the specified file does not exist or any other error occurs, the code within catch block
executes as shown in the below output.

Output:

Exception in thread "main" java.io.FileNotFoundException: Test.txt (The system cannot find


the file specified) at java.base/java.io.FileInputStream.open0(Native Method)

Runtime Exception: (Unchecked Exception)


1. Arithmetic Exception- It is thrown when an exceptional condition has occurred in an arithmetic
operation.
class ArithmeticException_Demo {
public static void main(String args[])
{
try {
int a = 30, b = 0;
int c = a / b; // cannot divide by zero
System.out.println("Result = " + c);
}
catch (ArithmeticException e) {
System.out.println("Can't divide a number by 0");
}
}
}

Output:
Can’t divide a number by 0

2.ArrayIndexOutOfBounds Exception: It is thrown to indicate that an array has been accessed with
an illegal index. The index is either negative or greater than or equal to the size of the array.
class ArrayIndexOutOfBound_Demo {
public static void main(String args[])
{
try {
int a[] = new int[5];
a[6] = 9; // accessing 7th element in an array of
// size 5
}
catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array Index is Out Of Bounds");
}
}
}
Output:

Array Index is Out Of Bounds

3. ClassNotFoundException: This exception is raised when program try to access a class whose
definition is not found.

4. FileNotFoundException: This exception is raised when a file is not accessible or does not open.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
class File_notFound_Demo {

public static void main(String args[])


{
try {

// Following file does not exist


File file = new File("E:// file.txt");
FileReader fr = new FileReader(file);
}
catch (FileNotFoundException e) {
System.out.println("File does not exist");
}
}
}

Output:

File does not exist

5. Null Pointer Exception: This exception is raised when referring to the members of a null object. Null
represents nothing

class NullPointer_Demo {
public static void main(String args[])
{
try
{
String a = null; // null value
System.out.println(a.charAt(0));
}
catch (NullPointerException e)
{
System.out.println("NullPointerException..");
}
}
}

Output: NullPointerException

User-Defined Exception:
Java user-defined exception is a custom exception created and throws that exception using
a keyword ‘throw’. It is done by extending a class ‘Exception’.

Scenario:

In any banking application, the major modules are deposits and withdrawals. When
performing a withdrawal from a bank account, it is required to validate the minimum balance in the
account.
To validate this requirement Java didn’t provide any specific exception class. Hence to
handle this requirement, a user-defined exception MinimumAccountBalance may be created.

Example Program:

import java.util. Scanner;


class MinimumAccountBalance extends Exception
{
String message;
public MinimumAccountBalance(String message)
{
this.message = message;
}
@Override
public String toString()
{
return message;
}
}

public class UserDefinedException


{
static double current_balance = 100;
public static void main(String[] args) throws MinimumAccountBalance
{
Scanner s = new Scanner(System.in);
System.out.println("Enter amount to withdrawal");
int n = s.nextInt();
try {
if (current_balance < n)
{
throw new MinimumAccountBalance("Insufficient funds ! your Current balance is " +
current_balance);
}

else
{
System.out.println("Please Take The Money : " + n);
}
}
catch (MinimumAccountBalance mab)
{
mab.printStackTrace();
}
}
}

Output:
D:\javaprograms>javac UserDefinedException.java

D:\javaprograms>java UserDefinedException
Enter amount to withdrawal
500
Insufficient funds ! your Current balance is 100.0
at UserDefinedException.main(UserDefinedException.java:27)

D:\javaprograms>java UserDefinedException
Enter amount to withdrawal
50
Please Take The Money : 50
Multithreaded Programming: Java Thread Model
Multitasking is a process of executing multiple tasks simultaneously. The concept of
multitasking is to utilize the CPU at its Maximum. Multitasking can be achieved in two ways:

o Process-based Multitasking (Multiprocessing)

o Thread-based Multitasking (Multithreading)

Process-based Multitasking (Multiprocessing)

o Each process has an address in memory. In other words, each process allocates a
separate memory area.
o A process is heavyweight.
o Cost of communication between the process is high.
o Context Switching from one process to another is costly and it requires some time
for saving and loading registers, memory maps, updating lists, etc.

Thread-based Multitasking (Multithreading)

o Threads share the same address space (code & data).


o A thread is lightweight.
o Cost of communication between the thread is low.

Process

Process simply means a program in execution. Processes have their own separate address
space (their own code & data) & use more resources and hence they are termed as heavyweight
process.

The above diagram shows how the resources are shared in two different processes vs two
threads in a single process.
Thread

➢ Thread is a sequential flow of tasks within a process. Threads are used to increase the
performance of the applications.
➢ Each thread has its own program counter, stack, and set of registers. But the threads of a
single process might share the same code and data/file. Threads are also termed as
lightweight processes as they share common resources.
➢ Eg: While playing a movie on a device the audio and video are controlled by different
threads in the background.

The above diagram shows the difference between a single-threaded process and a multithreaded
process and the resources that are shared among threads in a multithreaded process.

Multithreading

In Multithreading, the idea is to divide a single process into multiple threads instead of
creating a whole new process. Multithreading is done to achieve parallelism and to improve the
performance of the applications

Java provides built-in support for multithreaded programming. A Multithreaded program


contains two or more parts that can run concurrently. Each part of such a program is called a thread
and each thread defines a separate path of execution. Thus multithreading is a specialized form of
multitasking.
Advantages of Multithreading

i) Resource Sharing:

Threads of a single process share the same resources such as code, data/file.

ii) Responsiveness:

Program responsiveness enables a program to run even if part of the program is blocked or
executing a lengthy operation. Thus, increasing the responsiveness to the user.

iii)Economy:

It is more economical to use threads as they share the resources of a single process. On the
other hand, creating processes is expensive.

Process Vs Thread

Process Thread
Processes use more resources and hence
Threads share resources and hence they are
they are termed as heavyweight
termed as lightweight processes.
processes.
Creation and termination times of Creation and termination times of threads are
processes are slower. faster compared to processes.
Processes have their own code and
Threads share code and data/file within a process.
data/file.
Communication between processes is
Communication between threads is faster.
slower.
Context Switching in processes is slower.Context switching in threads is faster.
Threads, on the other hand, are interdependent.
Processes are independent of each other. (i.e they can read, write or change another
thread’s data)
Eg: Opening two different browsers. Eg: Opening two tabs in the same browser.

Types of Thread:
1.Userlevel Thread
User-level threads are implemented and managed by the user and the kernel is not aware of it.

• User-level threads are implemented using user-level libraries and the OS does not recognize
these threads.
• User-level thread is faster to create and manage compared to kernel-level thread.
• Context switching in user-level threads is faster.
• If one user-level thread performs a blocking operation then the entire process gets blocked.
Eg: POSIX threads, Java threads, etc.
2. Kernel level Thread:
Kernel level threads are implemented and managed by the OS.

• Kernel level threads are implemented using system calls and Kernel level threads are
recognized by the OS.
• Kernel-level threads are slower to create and manage compared to user-level threads.
• Context switching in a kernel-level thread is slower.
• Even if one kernel-level thread performs a blocking operation, it does not affect other threads.
Eg: Window Solaris.

Advantages of Threading:

• Threads improve the overall performance of a program.


• Threads increases the responsiveness of the program
• Context Switching time in threads is faster.
• Threads share the same memory and resources within a process.
• Communication is faster in threads.
• Threads provide concurrency within a process.
• Enhanced throughput of the system.
• Since different threads can run parallelly, threading enables the utilization of the
multiprocessor architecture to a greater extent and increases efficiency.
Java Thread Model:

1. Single Threaded Model or Single Thread System


➢ Single-threaded systems use an approach called an event loop with polling. In this
model, a single thread of control runs in an infinite loop, polling a single event queue to
decide what to do next.

➢ Once this polling mechanism returns with, For example., a signal that a network file is
ready to be read, then the event loop dispatches control to the appropriate event
handler. Until this event handler returns, nothing else can happen in the program. This
wastes CPU time. It can also result in one part of a program dominating the system and
preventing any other events from being processed.

➢ In general, in a single threaded environment, when a thread blocks (that is, suspends
execution) because it is waiting for some resource, the entire program stops running.

2. Multi-Threaded Model or Single Thread System:


The benefit of Java’s multithreading is that the main loop/polling mechanism is
eliminated. When a thread blocks in a Java program, only the single thread that is blocked
pauses. All other threads continue to run.

Java’s Multithreading Features Support in both Single Core Systems and Multi core Systems.

Single Core Systems:

In a single-core system, concurrently executing threads share the CPU, with each thread
receiving a slice of CPU time. Therefore, in a single-core system, two or more threads do not
actually run at the same time, but idle CPU time is utilized.

Multi Core Systems:

In multicore systems, it is possible for two or more threads to actually execute simultaneously.
This ability can improve program efficiency and increase the speed of operations.
Thread States:

A thread in java goes through five states in the span of its creation to its termination

1. New state: 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.

2. Active state: A thread moves from the new state to the active state when the thread invokes
the start() method. The thread in the active state can be in a runnable state or a running state.

Runnable state: After the creation of thread in java, when the thread is ready to run, it is
moved from the new state to the runnable state. During the runnable state, the thread
may be running or may be ready to run at any given instant of time. In the runnable state,
there is a queue where the threads lie.

Running state: A thread is moved from the runnable state to the running state by the
thread scheduler for its execution. By the running state, the thread gets the CPU for its
execution. Always a fixed duration of execution time is allocated to a thread in java.

3. Waiting or blocked state: Whenever a thread in java goes to an inactive state for some time (period
i.e. not permanently), then the thread is present in the waiting or blocked state.

Whenever the main thread calls the join() method (to attach itself with other thread(s)), then
the main method or main thread goes into the waiting state. After invoking the join() method,
the main thread waits for its child thread to be executed first.

When the child thread completed its execution, it sends a signal back to the main thread. after
getting the completion signal for the child thread, the main thread is moved from the waiting
state to the active state.

Sometimes when a thread is working on data that is being used by some other thread then the
current thread waits to acquire a lock on the shared data. This state is referred to as the
locking state.

4.Timed Waiting state: when a process is waiting, and it continues to wait for a longer duration
then the process is said to be in the timed waiting state. A thread can also move in the timed
waiting state if the thread invokes a method with the time-out parameter. The thread exits the
timed waiting state when the timeout is completed or the waiting resources are gained.
5. Terminated state: When the thread completes its instruction cycle (completes execution), the
thread goes into the termination state. A thread may also go into the termination state due to
some error. When the thread is not handled correctly or when some other execution(s) is raised by
the thread then the thread is terminated as abnormal termination.

When starts the JVM or the Java Virtual Machine, a single thread (typically called the main method)
is started. This main thread continues and executed other threads until the following conditions are
met:

1. The exit() method has been called up.

2. All the other threads have exited after executing their instructions.

Thread Scheduler:

The allocation of time of execution to a thread is governed by a thread scheduler.

A thread in java is executed as per the priority. The thread with higher priority is executed first
then the threads with lower priorities are executed.
CREATING A THREAD AND MULTIPLE THREADS

There are two ways to create a thread:

1. By extending Thread class


2. By implementing Runnable interface.

1. By extending 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:

i) Thread()

ii) Thread(String name)

iii) Thread(Runnable r)

iv) 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 String getName(): returns the name of the thread.

5. public void setName(String name): changes the name of the thread.

6. public Thread currentThread(): returns the reference of currently executing thread.

7. public int getId(): returns the id of the thread.

8. public Thread.State getState(): returns the state of the thread.

9. public void join(): waits for a thread to die.

10. public void join(long miliseconds): waits for a thread to die for the specified miliseconds.

11.public void interrupt(): interrupts the 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.

Java Thread Example by extending Thread class

class Multi extends Thread{

public void run(){

System.out.println("thread is running...");

public static void main(String args[]){

Multi t1=new Multi();

t1.start();

Output:

thread is running…

2. By implementing 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().

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


Java Thread Example by implementing Runnable interface

class Multi3 implements Runnable{


public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
Multi3 m1=new Multi3();
Thread t1 =new Thread(m1); // Using the constructor Thread(Runnable r)
t1.start();
}
}
Output:

thread is running…

3. Using the Thread class: Thread(String name)

public class MyThread1


{
// 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");
// the start() method moves the thread to the active state
t.start();
// getting the thread name by invoking the getName() method
String str = t.getName();
System.out.println(str);
}
}
Output:

My first thread
Creating Multiple Threads

class NewThread implements Runnable


{
String name; //name of thread
Thread t;
NewThread(String threadname)
{
name=threadname;
t=new Thread(this,name);
System.out.println("New thread:"+t);
}
//This is the entry point for thread
public void run()
{
try
{
for(int i=5;i>0;i--)
{
System.out.println(name+":"+i);
Thread.sleep(1000);
}
}
catch(InterruptedException e)
{
System.out.println(name+"Interrupted");
}
System.out.println(name+"exiting.");
}
}
class MultiThreadDemo
{
public static void main(String args[])
{
NewThread nt1=new NewThread("One");
NewThread nt2=new NewThread("Two");
NewThread nt3=new NewThread("Three");

//Start the threads.


nt1.t.start();
nt2.t.start();
nt3.t.start();
try
{
//wait for other threads to end
Thread.sleep(1000);
}
catch(InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}

Output:
D:\javaprograms>java MultiThreadDemo
New thread:Thread[#20,One,5,main]
New thread:Thread[#21,Two,5,main]
New thread:Thread[#22,Three,5,main]
Three:5
Two:5
One:5
Main thread exiting.
Two:4
Three:4
One:4
Three:3
Two:3
One:3
Two:2
Three:2
One:2
Two:1
Three:1
One:1
Three exiting.
Two exiting.
One exiting.

THREAD PRIORITIES
Thread priorities are used by the thread scheduler to decide when each thread should be
allowed to run. 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 .

➢ To set a thread’s priority, use the setPriority( ) method, which is a member of Thread
class.

Syntax: final void setPriority(int level)

Here, level specifies the new priority setting for the calling thread. The value of level
must be within the range MIN_PRIORITY and MAX_PRIORITY. Currently, these values are 1 and 10,
respectively. To return a thread to default priority, specify NORM_PRIORITY, which is currently 5.
These priorities are defined as static final variables within Thread.

➢ To obtain the current priority, use the getPriority() method which is a member of Thread
class

Syntax: final int getPriority()

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.


Thread Synchronization:

➢ When two or more threads need access to a shared resource, they need some way to ensure
that the resource will be used by only one thread at a time. The process by which this is
achieved is called synchronization.

➢ There are two types of thread synchronization mutual exclusive and inter-thread
communication.

1. Mutual Exclusive
i. Synchronized method.
ii. Synchronized block
iii. Static Synchronization
2. Inter-thread communication (Cooperation)

Concept of Monitor or Lock in java

Key to synchronization is the concept of the monitor. A monitor is an object that is used as a
mutually exclusive lock.

Only one thread can own a monitor at a given time. When a thread acquires a lock, it is said to
have entered the monitor. All other threads attempting to enter the locked monitor will be
suspended until the first thread exits the monitor.

These other threads are said to be waiting for the monitor. A thread that owns a monitor can
reenter the same monitor if it so desires.

Understanding the problem without Synchronization:

In this example, there is no synchronization, so output is inconsistent.

class Table{
void printTable(int n){//method not synchronized
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}

Output:
5
100
10
200
15
300
20
400
25
500
Java Synchronized Method
A method which is declared with the keyword synchronized is known as synchronized method.
Synchronized method is used to lock an object for any shared resource. When a thread invokes a
synchronized method, it automatically acquires the lock for that object and releases it when the
thread completes its task.

//example of java synchronized method


class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}

class MyThread1 extends Thread{


Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

public class TestSynchronization2{


public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
Output:
5
10
15
20
25
100
200
300
400
500

INTER THREAD COMMUNICATION

Inter-thread communication or Co-operation is a technique by which allow synchronised


threads to communicate with each other.

Cooperation (Inter-thread communication) is a mechanism in which a thread is paused


running in its critical section and another thread is allowed to enter (or lock) in the same critical
section to be executed. Inter thread communication in Java can be achieved by using three methods
provided by Object class of java.lang package.

o wait()
o notify()
o notifyAll()

1) Wait() Method

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. In case, the wait() method doesn’t take argument, it waits indefinitely for any other
thread to call notify() or notifyAll() method on the object to wake up the current thread.

The current thread must own this object's monitor, so it must be called from the synchronized
method only otherwise it will throw exception.

Method Description

public final void wait()throws InterruptedException It waits until object is notified.

public final void wait(long timeout)throws It waits for the specified amount of
InterruptedException time.
2) notify() Method

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.

Syntax:
public final void notify()

3) notifyAll() Method

Wakes up all threads that are waiting on this object's monitor.

Syntax:
public final void notifyAll()

Example Program: Inter Thread Communication


class Customer
{
int amount=10000;

synchronized void withdraw(int amount)


{

System.out.println("going to withdraw...Withdrawal amount is"+amount);

System.out.println("Actual Balance is"+this.amount);


if(this.amount<amount)
{
System.out.println("Less balance; waiting for deposit...");
try
{
wait();
}
catch(Exception e)
{
}
}
this.amount-=amount;
System.out.println("Balance amount after withdraw..."+this.amount);
}
synchronized void deposit(int amount)
{
System.out.println("going to deposit...");
System.out.println("Balance before deposit:"+this.amount);
this.amount+=amount;
System.out.println("Balance amount after deposit... "+this.amount);
notify();
}
}

class MyThread1 extends Thread


{
Customer c;

MyThread1(Customer c)
{
this.c=c;
}

public void run()


{
c.withdraw(15000);
}
}

class MyThread2 extends Thread


{
Customer c;
MyThread2(Customer c)
{
this.c=c;
}

public void run()


{
c.deposit(10000);
}
}

class Test
{
public static void main(String args[])
{
Customer c=new Customer();
MyThread1 t1 = new MyThread1(c);
MyThread2 t2 = new MyThread2(c);
t1.start();
t2.start();
}
}

Output:

D:\javaprograms>java Test
going to withdraw...Withdrawal amount is15000
Actual Balance is10000
Less balance; waiting for deposit...
going to deposit...
Balance before deposit:10000
Balance amount after deposit... 20000
Balance amount after withdraw...5000

Suspending-Resuming and Stopping Threads-MultiThreading

Suspending Threads in Java


In Java, a thread can be suspended by using the wait() method on an object. This method
suspends thread execution until it is notified by another thread using the notify() method.

Resuming Threads in Java

An interrupted thread's execution can be picked back up by notifying the waiting thread using
the notify() method.

Stopping Threads in Java

To halt a running thread, use a boolean flag to signal the thread to stop gracefully.

Example Program (Suspending/Resuming/Stopping Thread)

//Suspending and resuming a thread the modern way


class NewThread implements Runnable
{
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname)
{
name=threadname;
t=new Thread(this,name);
System.out.println("New Thread:"+t);
suspendFlag=false;
}
//This is the entry point for thread.
public void run()
{
try
{
for(int i=15;i>0;i--)
{
System.out.println(name+":"+i);
Thread.sleep(200);
synchronized(this)
{
while(suspendFlag)
{
wait();
}
}
}
}
catch(InterruptedException e)
{
System.out.println(name+"interrupted.");
}
System.out.println(name+"exiting.");
}//end of run() method

synchronized void mysuspend()


{
suspendFlag=true;
}
synchronized void myresume()
{
suspendFlag=false;
notify();
}
}// end of class NewThread
class SuspendResume
{
public static void main(String args[])
{
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");

ob1.t.start(); //start the thread


ob2.t.start(); //start the thread

try
{
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread one");

Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming thread one");

ob2.mysuspend();
System.out.println("Suspending thread Two");

Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
}
catch(InterruptedException e)
{
System.out.println("Main thread Interrupted");
}

//wait for threads to finish


try
{
System.out.println("waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
}
catch(InterruptedException e)
{
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");

}//end of main() Method


}// end of SuspendResume class

Output:
New Thread:Thread[#20,One,5,main]
New Thread:Thread[#21,Two,5,main]
Two:15
One:15
One:14
Two:14
Two:13
One:13
One:12
Two:12
One:11
Two:11
Suspending thread one
Two:10
Two:9
Two:8
Two:7
Two:6
Resuming thread one
One:10
Suspending thread Two
One:9
One:8
One:7
One:6
Resuming thread Two
One:5
Two:5
waiting for threads to finish.
One:4
Two:4
One:3
Two:3
One:2
Two:2
One:1
Two:1
Oneexiting.
Twoexiting.
Main thread exiting.
Wrappers
A wrapper class in Java is used to represent a primitive data type as an object. For
example, the Integer wrapper class can be used to represent and perform operations on integer
values.

For Example:
Integer myNumber = new Integer(10);
int value = myNumber.intValue();
System.out.println(value); // Output: 10

Java provides wrapper classes for each primitive data type. The wrapper classes are: -
Integer - Byte - Short - Long - Float - Double - Character - Boolean

Primitive Type Wrapper class

boolean Boolean

char Character

byte Byte

short Short

int Integer

long Long

float Float

double Double
Need of Wrapper class in java:
Wrapper classes provide additional functionality and features that are not available with
primitive data types. It allows to treat primitive values as objects and provide methods for
conversions, comparisons, and other operations. Wrapper classes are also useful in Java collections
and when working with APIs that require objects.

1. Primitive Types to Wrapper Objects

class Main {
public static void main(String[] args) {
// create primitive types
int a = 5;
double b = 5.65;
//converts into wrapper objects
Integer aObj = Integer.valueOf(a);
Double bObj = Double.valueOf(b);
if(aObj instanceof Integer) {
System.out.println("An object of Integer is created.");
System.out.println("The value stored in aObj is:"+aObj);
}
if(bObj instanceof Double) {
System.out.println("An object of Double is created.");
System.out.println("The value stored in bObj is:"+bObj);
}
}
}
Output:
D:\javaprograms>javac MainWrapper.java
D:\javaprograms>java MainWrapper
An object of Integer is created.
The value stored in aObj is:5
An object of Double is created.
The value stored in bObj is:5.65
Autoboxing:
Autoboxing is when the Java compiler performs the automatic conversion of the primitive data
types to the object of their corresponding wrapper classes. For example, converting an int to Integer,
a double to Double, etc.

//Autoboxing example of int to Integer and char to Char

public class AutoboxingExample {


public static void main(String args[]) {
char ch = 's';
//Autoboxing- primitive to Character object conversion
Character s = ch;
int a = 50;
// Converting int into Integer explicitly
Integer first = Integer.valueOf(a);
// Autoboxing, now compiler will write Integer.valueOf(a)
// internally and hence, doesn't generate an error
Integer second = a;
System.out.println(a);
System.out.println(first);
System.out.println(second);
}
}

Output:
50
50
50
Unboxing:

Unboxing is automatically converting an object of a wrapper type (Integer, for example) to its
corresponding primitive (int) value.

The Java compiler applies unboxing when an object of a wrapper class is:

• Passed as a parameter to a method that expects a value of the corresponding primitive type.
• Assigned to a variable of the corresponding primitive type.

Example Program:
//Unboxing example of Integer to int and Character to char
public class UnboxingExample {
public static void main(String args[]) {
Character ch = 's';
//Unboxing - Character object to primitive conversion
char s = ch;
Integer a = new Integer(5);
//Converting Integer to int explicitly
int first = a.intValue();
//Unboxing, now compiler will write a.intValue() internally
int second = a;
System.out.println(a);
System.out.println(first);
System.out.println(second);
}
}

Output:
5
5
5

You might also like