0% found this document useful (0 votes)
15 views44 pages

Unit III

Uploaded by

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

Unit III

Uploaded by

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

UNIT III

Exception Handling in Java

What are Java Exceptions?

In Java, Exception is an unwanted or unexpected event, which occurs during the execution of a program, i.e. at run time,
that disrupts the normal flow of the program’s instructions. Exceptions can be caught and handled by the program. When
an exception occurs within a method, it creates an object. This object is called the exception object. It contains information
about the exception, such as the name and description of the exception and the state of the program when the exception
occurred.

Major reasons why an exception Occurs

Invalid user input

Device failure

Loss of network connection

Physical limitations (out-of-disk memory)

Code errors

Opening an unavailable file

Errors represent irrecoverable conditions such as Java virtual machine (JVM) running out of memory, memory leaks, stack
overflow errors, library incompatibility, infinite recursion, etc. Errors are usually beyond the control of the programmer, and
we should not try to handle errors.

Types of Java Exceptions

1.Checked Exception

2.Unchecked Exception

3.Error

1) Checked Exception

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 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.

Java Exception Keywords

try The "try" keyword is used to specify a block where we should place an exception code. It means we can't use try
block alone. The try block must be followed by either catch or finally.
catch The "catch" block is used to handle the exception. It must be preceded by try block which means we can't use catch
block alone. It can be followed by finally block later.

finally The "finally" block is used to execute the necessary code of the program. It is executed whether an exception is
handled or not.

throw The "throw" keyword is used to throw an exception.

throws The "throws" keyword is used to declare exceptions. It specifies that there may occur an exception in the method. It
doesn't throw an exception. It is always used with method signature.

Java Exception Handling Example

public class JavaExceptionExample{

public static void main(String args[]){

try{

//code that may raise exception

int data=100/0;

}catch(ArithmeticException e)

System.out.println(e);

//rest code of the program

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

OUTPUT

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

rest of the code...

Java try block

Java try block is used to enclose the code that might throw an exception. It must be used within the method.

If an exception occurs at the particular statement in the try block, the rest of the block code will not execute. So, it is
recommended not to keep the code in try block that will not throw an exception.

Java try block must be followed by either catch or finally block.

Syntax of Java try-catch


try{

//code that may throw an exception

}catch(Exception_class_Name ref){}

Syntax of try-finally block

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.

The catch block must be used after the try block only. You can use multiple catch block with a single try block.

Internal Working of Java try-catch block

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.
Example 1

TryCatchExample1.java

public class TryCatchExample1 {

public static void main(String[] args) {

int data=50/0; //may throw exception

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

Output:

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

As displayed in the above example, the rest of the code is not executed (in such case, the rest of the code statement is not
printed).

There might be 100 lines of code after the exception. If the exception is not handled, all the code below the exception won't
be executed.

Solution by exception handling

Let's see the solution of the above problem by a java try-catch block.

Example 2

TryCatchExample2.java

public class TryCatchExample2 {

public static void main(String[] args) {

try

int data=50/0; //may throw exception

//handling the exception

catch(ArithmeticException e)
{

System.out.println(e);

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

OUTPUT

java.lang.ArithmeticException: / by zero

rest of the code

As displayed in the above example, the rest of the code is executed, i.e., the rest of the code statement is printed.

Java Multi-catch block

A try block can be followed by one or more catch blocks. Each catch block must contain a different exception handler. So, if
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.you have to perform different tasks at the occurrence of different exceptions, use java multi-catch block.
Example 1

Let's see a simple example of java multi-catch block.

MultipleCatchBlock1.java

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 2

MultipleCatchBlock2.java

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

Java Nested try block

In Java, using a try block inside another try block is permitted. It is called as nested try block. Every statement that we enter
a statement in try block, context of that exception is pushed onto the stack.

For example, the inner try block can be used to handle ArrayIndexOutOfBoundsException while the outer try block can
handle the ArithemeticException (division by zero).

Why use nested try block

Sometimes a situation may arise where a part of a block may cause one error and the entire block itself may cause another
error. In such cases, exception handlers have to be nested.
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

....

Java Nested try Example

Example 1

Let's see an example where we place a try block within another try block for two different exceptions.

NestedTryBlock.java

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..");

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.

class Nesting {

// main method

public static void main(String args[])

// main try-block

try {

// try-block2

try {
// try-block3

try {

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

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

// handles ArithmeticException if any

catch (ArithmeticException e) {

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

System.out.println(" try-block1");

// handles ArithmeticException if any

catch (ArithmeticException e) {

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

System.out.println(" try-block2");

// handles ArrayIndexOutOfBoundsException if any

catch (ArrayIndexOutOfBoundsException e4) {

System.out.print("ArrayIndexOutOfBoundsException");

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

catch (Exception e5) {

System.out.print("Exception");

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

Output:
ArrayIndexOutOfBoundsException main try-block

Built-in Exceptions in Java

Built-in exceptions are the exceptions which are available in Java libraries.

Exceptions that are already available in Java libraries are referred to as built-in exception. These exceptions are able to
define the error situation so that we can understand the reason of getting this error. It can be categorized into two broad
categories, i.e., checked exceptions and unchecked exception.

Examples of Built-in Exception:

Arithmetic exception :It is thrown when an exceptional condition has occurred in an arithmetic operation.

// Java program to demonstrate

// ArithmeticException

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

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.

Example 2

// Java program to demonstrate

// ArrayIndexOutOfBoundException

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

Java Custom Exception

In Java, we can create our own exceptions that are derived classes of the Exception class. Creating our own Exception is
known as custom exception or user-defined exception. Basically, Java custom exceptions are used to customize the
exception according to user need.

An exception is an issue (run time error) that occurred during the execution of a program. When an exception occurred the
program gets terminated abruptly and, the code past the line that generated the exception never gets executed.

Java provides us the facility to create our own exceptions which are basically derived classes of Exception. Creating our own
Exception is known as a custom exception or user-defined exception. Basically, Java custom exceptions are used to
customize the exception according to user needs. In simple words, we can say that a User-Defined Exception or custom
exception is creating your own exception class and throwing that exception using the ‘throw’ keyword.

Following are a few of the reasons to use custom exceptions:

To catch and provide specific treatment to a subset of existing Java exceptions.

Business logic exceptions: These are the exceptions related to business logic and workflow. It is useful for the application
users or the developers to understand the exact problem.

In order to create a custom exception, we need to extend the Exception class that belongs to java.lang package.

// A Class that represents use-defined exception

class MyException extends Exception {

// A Class that uses above MyException

public class setText {

// Driver Program

public static void main(String args[])


{

try {

// Throw an object of user defined exception

throw new MyException();

catch (MyException ex) {

System.out.println("Caught");

System.out.println(ex.getMessage());

Output

Caught

Null

THREAD

A Thread is a very light-weighted process, or we can say the smallest part of the process that allows a program to operate
more efficiently by running multiple tasks simultaneously. In a program or process, all the threads have their own separate
path for execution, so each thread of a process is independent.

MULTITHREADING

Another benefit of using thread is that if a thread gets an exception or an error at the time of its execution, it doesn't affect
the execution of the other threads. All the threads share a common memory and have their own stack, local variables and
program counter. When multiple threads are executed in parallel at the same time, this process is known as Multithreading.

In a simple way, a Thread is a:

Feature through which we can perform multiple activities within a single process.

Lightweight process.

Series of executed statements.

Nested sequence of method calls.

Thread Model

Just like a process, a thread exists in several states. These states are as follows:
1) New (Ready to run)

A thread is in New when it gets CPU time.

2) Running

A thread is in a Running state when it is under execution.

3) Suspended

A thread is in the Suspended state when it is temporarily inactive or under execution.

4) Blocked

A thread is in the Blocked state when it is waiting for resources.

5) Terminated

A thread comes in this state when at any given time, it halts its execution immediately.

Creating Thread

A thread is created either by "creating or implementing" the Runnable Interface or by extending the Thread class. These are
the only two ways through which we can create a thread.

Thread Class

A Thread class has several methods and constructors which allow us to perform various operations on a thread. The Thread
class extends the Object class. The Object class implements the Runnable interface. The thread class has the following
constructors that are used to perform various operations.

Thread()

Thread(Runnable, String name)

Thread(Runnable target)

Thread(ThreadGroup group, Runnable target, String name)

Thread(ThreadGroup group, Runnable target)


Thread(ThreadGroup group, String name)

Thread(ThreadGroup group, Runnable target, String name, long stackSize)

Runnable Interface(run() method)

The Runnable interface is required to be implemented by that class whose instances are intended to be executed by a
thread. The runnable interface gives us the run() method to perform an action for the thread.

start() method

The method is used for starting a thread that we have newly created. It starts a new thread with a new callstack. After
executing the start() method, the thread changes the state from New to Runnable. It executes the run() method when the
thread gets the correct time to execute it.

Java Threads

Threads allows a program to operate more efficiently by doing multiple things at the same time.

Threads can be used to perform complicated tasks in the background without interrupting the main program.

Creating a Thread

There are two ways to create a thread.

It can be created by extending the Thread class and overriding its run() method:

Extend Syntax

public class Main extends Thread {

public void run() {

System.out.println("This code is running in a thread");

Another way to create a thread is to implement the Runnable interface:

Implement Syntax

public class Main implements Runnable {

public void run() {

System.out.println("This code is running in a thread");

Running Threads

If the class extends the Thread class, the thread can be run by creating an instance of the class and call its start() method:

Extend Example

public class Main extends Thread {


public static void main(String[] args) {

Main thread = new Main();

thread.start();

System.out.println("This code is outside of the thread");

public void run() {

System.out.println("This code is running in a thread");

OUTPUT

This code is outside of the thread

This code is running in a thread

If the class implements the Runnable interface, the thread can be run by passing an instance of the class to a Thread
object's constructor and then calling the thread's start() method:

Implement Example

public class Main implements Runnable {

public static void main(String[] args) {

Main obj = new Main();

Thread thread = new Thread(obj);

thread.start();

System.out.println("This code is outside of the thread");

public void run() {

System.out.println("This code is running in a thread");

OUTPUT

This code is outside of the thread

This code is running in a thread

Differences between "extending" and "implementing" Threads


The major difference is that when a class extends the Thread class, you cannot extend any other class, but by implementing
the Runnable interface, it is possible to extend from another class as well, like: class MyClass extends OtherClass
implements Runnable.

Java Thread Priority in Multithreading

Whenever we create a thread in Java, it always has some priority assigned to it. Priority can either be given by JVM while
creating the thread or it can be given by the programmer explicitly.

Priorities in threads is a concept where each thread is having a priority which in layman’s language one can say every object
is having priority here which is represented by numbers ranging from 1 to 10.

The default priority is set to 5 as excepted.

Minimum priority is set to 1.

Maximum priority is set to 10.

Here 3 constants are defined in it namely as follows:

public static int NORM_PRIORITY

public static int MIN_PRIORITY

public static int MAX_PRIORITY

We will use currentThread() method to get the name of the current thread. User can also use setName() method if he/she
wants to make names of thread as per choice for understanding purposes.

getName() method will be used to get the name of the thread.

The accepted value of priority for a thread is in the range of 1 to 10.

1.public final int getPriority(): java.lang.Thread.getPriority() method returns priority of given thread.

2.public final void setPriority(int newPriority):java.lang.Thread.setPriority() method changes the priority of thread to the
value newPriority. This method throws IllegalArgumentException if value of parameter newPriority goes beyond
minimum(1) and maximum(10) limit.

Example

// Java Program to Illustrate Priorities in Multithreading

// via help of getPriority() and setPriority() method

// Importing required classes

import java.lang.*;

// Main class

class ThreadDemo extends Thread {

// Method 1

// run() method for the thread that is called

// as soon as start() is invoked for thread in main()

public void run()


{

// Print statement

System.out.println("Inside run method");

// Main driver method

public static void main(String[] args)

// Creating random threads

// with the help of above class

ThreadDemo t1 = new ThreadDemo();

ThreadDemo t2 = new ThreadDemo();

ThreadDemo t3 = new ThreadDemo();

// Thread 1

// Display the priority of above thread

// using getPriority() method

System.out.println("t1 thread priority : "

+ t1.getPriority());

// Thread 1

// Display the priority of above thread

System.out.println("t2 thread priority : "

+ t2.getPriority());

// Thread 3

System.out.println("t3 thread priority : "

+ t3.getPriority());

// Setting priorities of above threads by

// passing integer arguments

t1.setPriority(2);
t2.setPriority(5);

t3.setPriority(8);

// t3.setPriority(21); will throw

// IllegalArgumentException

// 2

System.out.println("t1 thread priority : "

+ t1.getPriority());

// 5

System.out.println("t2 thread priority : "

+ t2.getPriority());

// 8

System.out.println("t3 thread priority : "

+ t3.getPriority());

// Main thread

// Displays the name of

// currently executing Thread

System.out.println(

"Currently Executing Thread : "

+ Thread.currentThread().getName());

System.out.println(

"Main thread priority : "

+ Thread.currentThread().getPriority());

// Main thread priority is set to 10


Thread.currentThread().setPriority(10);

System.out.println(

"Main thread priority : "

+ Thread.currentThread().getPriority());

Output

t1 thread priority : 5

t2 thread priority : 5

t3 thread priority : 5

t1 thread priority : 2

t2 thread priority : 5

t3 thread priority : 8

Currently Executing Thread : main

Main thread priority : 5

Main thread priority : 10

Output explanation:

Thread with the highest priority will get an execution chance prior to other threads. Suppose there are 3 threads t1, t2, and
t3 with priorities 4, 6, and 1. So, thread t2 will execute first based on maximum priority 6 after that t1 will execute and then
t3.The default priority for the main thread is always 5, it can be changed later. The default priority for all other threads
depends on the priority of the parent thread.

// Java program to demonstrate that a Child thread

// Getting Same Priority as Parent thread

// Importing all classes from java.lang package

import java.lang.*;

// Main class

// ThreadDemo

// Extending Thread class

class GFG extends Thread {

// Method 1

// run() method for the thread that is


// invoked as threads are started

public void run()

// Print statement

System.out.println("Inside run method");

// Method 2

// Main driver method

public static void main(String[] args)

// main thread priority is set to 6 now

Thread.currentThread().setPriority(6);

// Current thread is accessed

// using currentThread() method

// Print and display main thread priority

// using getPriority() method of Thread class

System.out.println(

"main thread priority : "

+ Thread.currentThread().getPriority());

// Creating a thread by creating object inside

// main()

GFG t1 = new GFG();

// t1 thread is child of main thread

// so t1 thread will also have priority 6

// Print and display priority of current thread


System.out.println("t1 thread priority : "

+ t1.getPriority());

Output

main thread priority : 6

t1 thread priority : 6

Output explanation:

If two threads have the same priority then we can’t expect which thread will execute first. It depends on the thread
scheduler’s algorithm(Round-Robin, First Come First Serve, etc)

If we are using thread priority for thread scheduling then we should always keep in mind that the underlying platform
should provide support for scheduling based on thread priority.

Synchronization in Java

Synchronization in Java is the capability to control the access of multiple threads to any shared resource.

Java Synchronization is better option where we want to allow only one thread to access the shared resource.

Why use Synchronization?

The synchronization is mainly used to

To prevent thread interference.

To prevent consistency problem.

Types of Synchronization

There are two types of synchronization

1.Process Synchronization

2.Thread Synchronization

Thread Synchronization

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

1.Mutual Exclusive

a.Synchronized method.

b.Synchronized block.

c.Static synchronization.

2.Cooperation (Inter-thread communication in java)

Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another while sharing data. It can be achieved by using the
following three ways:

By Using Synchronized Method

By Using Synchronized Block

By Using Static Synchronization

Concept of Lock in Java

Synchronization is built around an internal entity known as the lock or monitor. Every object has a lock associated with it. By
convention, a thread that needs consistent access to an object's fields has to acquire the object's lock before accessing
them, and then release the lock when it's done with them.

Understanding the problem without Synchronization

In this example, there is no synchronization, so output is inconsistent. Let's see the example:

TestSynchronization1.java

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:

100

10

200

15

300

20

400

25

500
Java Synchronized Method

If you declare any method as synchronized, it 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.

TestSynchronization2.java

//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:

10

15

20

25

100

200

300

400

500

Inter-thread Communication in Java

Inter-thread communication or Co-operation is all about allowing synchronized 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. It is implemented by following
methods of Object class:

1.wait()

2.notify()

3.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.

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 time.
InterruptedException

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()

Understanding the process of inter-thread communication

The point to point explanation of the above diagram is as follows:

1.Threads enter to acquire lock.

2.Lock is acquired by on thread.

3.Now thread goes to waiting state if you call wait() method on the object. Otherwise it releases the lock and exits.

4.If you call notify() or notifyAll() method, thread moves to the notified state (runnable state).
5.Now thread is available to acquire lock.

6.After completion of the task, thread releases the lock and exits the monitor state of the object.

Why wait(), notify() and notifyAll() methods are defined in Object class not Thread class?

It is because they are related to lock and object has a lock.

Difference between wait and sleep?

wait() sleep()

The wait() method releases the lock The sleep() method doesn't release the lock.
It is a method of Object class It is a method of Thread class

It is the non-static method It is the static method

It should be notified by notify() or notifyAll() methods After the specified amount of time, sleep is completed.

Example of Inter Thread Communication in Java

Test.java

class Customer{

int amount=10000;

synchronized void withdraw(int amount){

System.out.println("going to withdraw...");

if(this.amount<amount){

System.out.println("Less balance; waiting for deposit...");

try{wait();}catch(Exception e){}

this.amount-=amount;

System.out.println("withdraw completed...");

synchronized void deposit(int amount){

System.out.println("going to deposit...");

this.amount+=amount;

System.out.println("deposit completed... ");

notify();

}
class Test{

public static void main(String args[]){

final Customer c=new Customer();

new Thread(){

public void run(){c.withdraw(15000);}

}.start();

new Thread(){

public void run(){c.deposit(10000);}

}.start();

}}

Output:

going to withdraw...

Less balance; waiting for deposit...

going to deposit...

deposit completed...

withdraw completed

Suspending –Resuming, and Stopping Threads

Thread.stop() is being phased out due to its inherent risk. When you stop a thread, it unlocks all the monitors it has locked.
Other threads might see these objects in an inconsistent state if any of the objects previously protected by these monitors
were in an inconsistent state.

Threads acting on damaged objects can act erratically, whether consciously or unconsciously. ThreadDeath, unlike other
uncontrolled exceptions, silently kills threads, leaving the user with no warning that the program may be corrupted. After
the damage has occurred, the corruption may appear at an unpredicted moment. Also, killing a thread will create a
problem while working with DBMS – JDBC in a multithreaded environment.

Thread.suspend() is deprecated because it is inherently deadlock-prone. As a result, Thread.resume() must be deprecated


as well. When the target thread is suspended, it holds a lock on the monitor protecting a crucial system resource, and no
other thread may access it until the target thread is resumed. Deadlock occurs if the thread that would restart the target
thread tries to lock this monitor before invoking resume().

/ This class contains an integer array &

// Threads set the element's value for this array

class NumVal {

private int num[] = null;


boolean valueSet = false;

int i = 0;

NumVal()

// Creating integer array of 10 elements

num = new int[10];

// method to set the values in the array

public void setVal(int n)

if (i < 9) {

System.out.println("Putting value " + n

+ " in the NumVal Array");

num[i] = n;

i++;

// method to get the values from the array

public int getVal()

if (i >= 0) {

System.out.println("Giving n = " + num[i]);

i--;

return num[i + 1];

else {

return -1;

}
// Creating Our Thread Class

class MyThread extends Thread {

// MyThread want mutually exclusive

// lock on the object

// referred by: NumObjToSetVal

NumVal NumObjToSetVal = null;

// Constructor

public MyThread(String threadName, NumVal numV)

super(threadName);

NumObjToSetVal = numV;

public void run()

// Only 1 thread at a time an access the object

// referred by : NumObjToSetVal

synchronized (NumObjToSetVal)

int n = 0;

while (n < 5) {

System.out.println(

"THREAD NAME : "

+ Thread.currentThread().getName());

n++;

NumObjToSetVal.setVal(n);

try {

// Make the thread sleep for 100 ms

Thread.sleep(100);

System.out.println(

Thread.currentThread().getName()
+ "is awake now");

catch (Exception e) {

System.out.println("Exception Caught");

// If n is 2 , we suspend this thread

if (n == 2) {

// suspend the thread, now this thread

// will release lock on NumObjToSetVal

// only when resume() method is called

// on this thread, thread will go in

// waiting state

Thread.currentThread().suspend();

public class Main {

public static void main(String[] args)

// TODO Auto-generated method stub

NumVal v = new NumVal();

// Creating thread 1 that want exclusive lock on

// object referred by v

MyThread thread1 = new MyThread("Thread1 ", v);

// Creating thread 2 that want exclusive lock on

// object referred by v

// thread1 is not going to release lock on Object

// referred by v until resume() method is not called

// and for acquiring lock on v Object refred by v ,


// thread1 must have released lock on Object

// referred by v, if lock is not released, thread2

// will keep on waiting for thread1 to release lock

// onbject referred by v & deadlock will be formed

MyThread thread2 = new MyThread("Thread2 ", v);

// starting both threads

thread1.start();

thread2.start();

for (int i = 500; i <= 501; i++) {

System.out.println("Main Thread " + i);

Output:

THREAD NAME : Thread1

Putting value 1 in the NumVal Array

Main Thread 500

Main Thread 501

Thread1 is awake now

THREAD NAME : Thread1

Putting value 2 in the NumVal Array

Thread1 is awake now

//Deadlock is created & hence no output after this

Explanation: We created 2 threads: thread1 & thread2. Both want to acquire a lock on the NumVal object referred to by ‘v’
reference.

As we start both the threads by calling the start() method, the run() method will execute whenever the thread gets CPU.
Thread1 gets CPU & when the value of n is 2 in its run method, the thread is suspended. Thread1 is not going to release
lock on Object referred by ‘v’ until resume() is called on it.

For thread2 to acquire a lock on v Object referred by ‘v’, thread1 must have released the lock on Object referred by ‘v’. Here
the lock here is not released, thread2 will keep on waiting for thread1 to release the lock on the object referred by ‘v’ & a
deadlock will be formed.

So, you have always call resume() on a thread (at any time) whenever you call suspend() method on the same thread.

Multithreading in Java
Multithreading in Java is a process of executing multiple threads simultaneously.

A thread is a lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading, both are used to
achieve multitasking.

However, we use multithreading than multiprocessing because threads use a shared memory area. They don't allocate
separate memory area so saves memory, and context-switching between the threads takes less time than process.

Java Multithreading is mostly used in games, animation, etc.

Advantages of Java Multithreading

1) It doesn't block the user because threads are independent and you can perform multiple operations at the same time.

2) You can perform many operations together, so it saves time.

3) Threads are independent, so it doesn't affect other threads if an exception occurs in a single thread.

Multitasking

Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU. Multitasking
can be achieved in two ways:

1.Process-based Multitasking (Multiprocessing)

2.Thread-based Multitasking (Multithreading)

1) Process-based Multitasking (Multiprocessing)

Each process has an address in memory. In other words, each process allocates a separate memory area.

A process is heavyweight.

Cost of communication between the process is high.

Switching from one process to another requires some time for saving and loading registers, memory maps, updating lists,
etc.

2) Thread-based Multitasking (Multithreading)

Threads share the same address space.

A thread is lightweight.

Cost of communication between the thread is low.

Note: At least one process is required for each thread.

What is Thread in java

A thread is a lightweight subprocess, the smallest unit of processing. It is a separate path of execution.

Threads are independent. If there occurs exception in one thread, it doesn't affect other threads. It uses a shared memory
area.

// Java code for thread creation by extending

// the Thread class


class MultithreadingDemo extends Thread {

public void run()

try {

// Displaying the thread that is running

System.out.println(

"Thread " + Thread.currentThread().getId()

+ " is running");

catch (Exception e) {

// Throwing an exception

System.out.println("Exception is caught");

// Main Class

public class Multithread {

public static void main(String[] args)

int n = 8; // Number of threads

for (int i = 0; i < n; i++) {

MultithreadingDemo object

= new MultithreadingDemo();

object.start();

Output

Thread 15 is running

Thread 14 is running

Thread 16 is running
Thread 12 is running

Thread 11 is running

Thread 13 is running

Thread 18 is running

Thread 17 is running

Thread creation by implementing the Runnable Interface

We create a new class which implements java.lang.Runnable interface and override run() method. Then we instantiate a
Thread object and call start() method on this object.

// Java code for thread creation by implementing

// the Runnable Interface

class MultithreadingDemo implements Runnable {

public void run()

try {

// Displaying the thread that is running

System.out.println(

"Thread " + Thread.currentThread().getId()

+ " is running");

catch (Exception e) {

// Throwing an exception

System.out.println("Exception is caught");

// Main Class

class Multithread {

public static void main(String[] args)

int n = 8; // Number of threads

for (int i = 0; i < n; i++) {


Thread object

= new Thread(new MultithreadingDemo());

object.start();

Output

Thread 13 is running

Thread 11 is running

Thread 12 is running

Thread 15 is running

Thread 14 is running

Thread 18 is running

Thread 17 is running

Thread 16 is running

Thread Class vs Runnable Interface

If we extend the Thread class, our class cannot extend any other class because Java doesn’t support multiple inheritance.
But, if we implement the Runnable interface, our class can still extend other base classes.

We can achieve basic functionality of a thread by extending Thread class because it provides some inbuilt methods like
yield(), interrupt() etc. that are not available in Runnable interface.

Using runnable will give you an object that can be shared amongst multiple threads.

Wrapper classes in Java

The wrapper class in Java provides the mechanism to convert primitive into object and object into primitive.

Use of Wrapper classes in Java

Java is an object-oriented programming language, so we need to deal with objects many times like in Collections,
Serialization, Synchronization, etc. Let us see the different scenarios, where we need to use the wrapper classes.

Change the value in Method: Java supports only call by value. So, if we pass a primitive value, it will not change the original
value. But, if we convert the primitive value in an object, it will change the original value.

Serialization: We need to convert the objects into streams to perform the serialization. If we have a primitive value, we can
convert it in objects through the wrapper classes.

Synchronization: Java synchronization works with objects in Multithreading.

java.util package: The java.util package provides the utility classes to deal with objects.

Collection Framework: Java collection framework works with objects only. All classes of the collection framework (ArrayList,
LinkedList, Vector, HashSet, LinkedHashSet, TreeSet, PriorityQueue, ArrayDeque, etc.) deal with objects only.
Java Wrapper Classes

Wrapper classes provide a way to use primitive data types (int, boolean, etc..) as objects.

The table below shows the primitive type and the equivalent wrapper class:

Primitive Data Type Wrapper Class

byte Byte

short Short

int Integer

long Long

float Float

double Double
boolean Boolean

char Character

Creating Wrapper Objects

To create a wrapper object, use the wrapper class instead of the primitive type. To get the value, you can just print the
object:

Example

public class Main {

public static void main(String[] args) {

Integer myInt = 5;

Double myDouble = 5.99;

Character myChar = 'A';

System.out.println(myInt);

System.out.println(myDouble);

System.out.println(myChar);

OUTPUT

5.99

Since you're now working with objects, you can use certain methods to get information about the specific object.
For example, the following methods are used to get the value associated with the corresponding wrapper object: intValue(),
byteValue(), shortValue(), longValue(), floatValue(), doubleValue(), charValue(), booleanValue().

Another useful method is the toString() method, which is used to convert wrapper objects to strings.

In the following example, we convert an Integer to a String, and use the length() method of the String class to output the
length of the "string":

Example

public class Main {

public static void main(String[] args) {

Integer myInt = 100;

String myString = myInt.toString();

System.out.println(myString.length());

OUTPUT

Need of Wrapper Classes

There are certain needs for using the Wrapper class in Java as mentioned below:

1.They convert primitive data types into objects. Objects are needed if we wish to modify the arguments passed into a
method (because primitive types are passed by value).

2.The classes in java.util package handles only objects and hence wrapper classes help in this case also.

3.Data structures in the Collection framework, such as ArrayList and Vector, store only objects (reference types) and not
primitive types.

4.An object is needed to support synchronization in multithreading.

Advantages of Wrapper Classes

1.Collections allowed only object data.

2.On object data we can call multiple methods compareTo(), equals(), toString()

3.Cloning process only objects

4.Object data allowed null values.

5.Serialization can allow only object data.

Autoboxing and Unboxing:

The automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and opposite
operation is known as unboxing.
Advantage of Autoboxing and Unboxing:

No need of conversion between primitives and Wrappers manually so less coding is required.

Simple Example of Autoboxing in java:

class BoxingExample1{

public static void main(String args[]){

int a=50;

Integer a2=new Integer(a);//Boxing

Integer a3=5;//Boxing

System.out.println(a2+" "+a3);

Output:50 5

Simple Example of Unboxing in java:

The automatic conversion of wrapper class type into corresponding primitive type, is known as Unboxing.

class UnboxingExample1{

public static void main(String args[]){

Integer i=new Integer(50);

int a=i;

System.out.println(a);

Output:

50

Autoboxing and Unboxing with comparison operators

Autoboxing can be performed with comparison operators:

class UnboxingExample2{

public static void main(String args[]){


Integer i=new Integer(50);

if(i<100){ //unboxing internally

System.out.println(i);

Output:50

Autoboxing and Unboxing with method overloading

In method overloading, boxing and unboxing can be performed. There are some rules for method overloading with boxing:

1.Widening beats boxing

2.Widening beats varargs

3.Boxing beats varargs

1) Example of Autoboxing where widening beats boxing

If there is possibility of widening and boxing, widening beats boxing.

class Boxing1{

static void m(int i){System.out.println("int");}

static void m(Integer i){System.out.println("Integer");}

public static void main(String args[]){

short s=30;

m(s);

Output:int

2) Example of Autoboxing where widening beats varargs

If there is possibility of widening and varargs, widening beats var-args.

class Boxing2{
static void m(int i, int i2){System.out.println("int int");}

static void m(Integer... i){System.out.println("Integer...");}

public static void main(String args[]){

short s1=30,s2=40;

m(s1,s2);

Output:int int

3) Example of Autoboxing where boxing beats varargs

Let's see the program where boxing beats variable argument:

class Boxing3{

static void m(Integer i){System.out.println("Integer");}

static void m(Integer... i){System.out.println("Integer...");}

public static void main(String args[]){

int a=30;

m(a);

Output:Integer

Method overloading with Widening and Boxing

Widening and Boxing can't be performed as given below:

class Boxing4{

static void m(Long l){System.out.println("Long");}

public static void main(String args[]){

int a=30;

m(a);

}
Output:Compile Time Error

Java Autoboxing - Primitive Type to Wrapper Object

In autoboxing, the Java compiler automatically converts primitive types into their corresponding wrapper class objects. For
example,

int a = 56;

// autoboxing

Integer aObj = a;

Autoboxing has a great advantage while working with Java collections.

Example 1: Java Autoboxing

import java.util.ArrayList;

class Main {

public static void main(String[] args) {

ArrayList<Integer> list = new ArrayList<>();

//autoboxing

list.add(5);

list.add(6);

System.out.println("ArrayList: " + list);

Output

ArrayList: [5, 6]

In the above example, we have created an array list of Integer type. Hence the array list can only hold objects of Integer
type.

Notice the line,

list.add(5);

Here, we are passing primitive type value. However, due to autoboxing, the primitive value is automatically converted into
an Integer object and stored in the array list.

You might also like