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

Core JAVA

The document provides an overview of exception handling in Java, detailing types of errors, including compile-time and run-time errors, and the concept of exceptions. It explains the syntax for exception handling using try, catch, and finally blocks, and discusses the use of multiple catch statements and the throw keyword for creating custom exceptions. Additionally, it emphasizes the importance of managing errors to prevent program crashes and ensure smooth execution.
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)
14 views33 pages

Core JAVA

The document provides an overview of exception handling in Java, detailing types of errors, including compile-time and run-time errors, and the concept of exceptions. It explains the syntax for exception handling using try, catch, and finally blocks, and discusses the use of multiple catch statements and the throw keyword for creating custom exceptions. Additionally, it emphasizes the importance of managing errors to prevent program crashes and ensure smooth execution.
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/ 33

EXCEPTION HANDLING

Unit Structure

4.1 Introduction

4.2 Types of errors


4.3 Exceptions
4.4 Syntax of Exception Handling Code

4.5 Multiple catch Statements


4.6 Using finally Statement
4.7 Throw and throws keyword

4.9 Using Exception for debugging


4.9 Summary
4.10 Textbook
4.11 Additional References
4.12 Questions
4.1 INTRODUCTION
Rarely does a program run successfully at its very first attempt. It is very
common to make mistakes while developing as well as typing a program.
A mistake might lead to an error causing the program to produce
unexpected results. Errors can make a program go wrong.
An error may terminate the execution of the program or may produce an
incorrect output or even may cause the system to crash. It is important to
detect and manage properly all the possible error condition in the program
so that the program will not terminate/crash during execution.

4.2 TYPES OF ERRORS


Errors may be classified into two categories:

• Compile-time errors
• Run-time errors
Compile-Time Errors Exception Handling

All syntax errors are detected and displayed by the Java compiler and
hence these errors are known as compile-time errors. Whenever the
compiler displays an error, it will not create the .class file. Therefore, it is
necessary that we fix all the errors before we can successfully compile and
run the program.
Program 4.1 Illustration of compile-time errors
/*This program contains an error*/
class Error1
{
public static void main (String[] args)
{
System.out.println("Hello, World!")//Missing;
}
}
The Java compiler does a nice job of telling us where the errors have
occurred in the program. For example, if we have missed the semicolon at
the end of print statement in Program 4.1, the following message will
appear on the screen.

We can now go to the appropriate line, correct an error and recompile the
program. Sometimes, a single error may be the source of multiple errors
later in the compilation. For example, use of an undeclared variable in
several places will cause a series of errors of type “undefined variable”.
In such case, we should consider the earliest errors as the major source of
problem. Once we fix an error, we should recompile the program and look
for other errors.
Most of the compile-time errors are due to typing mistakes. Typographical
errors are hard to find, and we may have to check code word by word. The
most common problems are:
• Missing semicolons
• Missing (or mismatch of) brackets in classes and methods
• Misspelling of keywords and identifiers
• Missing double quotes in strings
• Using undeclared variables
• Use of = in place of == operator and so on.
Core JAVA Other errors may occur because of directory paths. An error such as

javac: command not found


It means that we have not set the path correctly. We must include
the path directory where the Java executables are stored.
Run-Time Errors
Sometimes, a program may compile successfully creating.class file but it
may not run properly. Such programs may produce incorrect output due to
wrong logic or may terminate due to errors such as stack overflow. Most
common run-time errors are:
• Dividing an integer by zero
• Accessing an element that is out of the bounds of an array
• Trying to store a value into an array of an incompatible class
• Passing a parameter that is not in a valid range or value for a method
• Trying to illegally change the state of a thread
• Attempting to use a negative size for an array
• Using a null object reference as a legitimate object reference to
access a method or a variable
• Converting invalid string to a number
• And many more
When such errors are encountered, Java typically generates an error
message and aborts the program. Program 4.2 illustrates how a run-time
error causes termination of execution of the program.
Program 4.2 Illustration of run-time errors
class Error2
{
public static void main(String[] args)
{
int x = 10;
int y = 5/0;
int z = 5/0;
int a = x/(y-z); //Division by zero
System.out.println("a=" +x); int b = x/(y+z);

System.out.println("b=" +y);

}
Program 4.2 is syntactically correct and therefore does not cause any Exception Handling
problem during compilation. However, during execution, it displays the
following message and stops without executing remaining statements.

When Java run-time tries to execute a division by zero, it generates an


error condition, which causes the program to stop after displaying an
appropriate message.

4.3 EXCEPTIONS
An exception is a condition caused by a run-time error in the program.
When the Java interpreter encounters an error such as dividing an integer
by zero, it creates and throws an exception object (i.e., informs us that an
error has occurred). If the exception object is not caught and handled
properly, the interpreter will display an error message as shown in the
output of Program 4.2 and will terminate the program.
If we want our program to continue with the execution of the remaining
code, then we should try to catch the exception object thrown by the error
condition and then display an appropriate message for taking corrective
actions. This task is known as exception handling.
The purpose of exception handling is to detect and report an “exceptional
circumstance” so that appropriate action can be taken. Error handling code
performs the following tasks:
1. Find the problem (Hit the exception).
2. Inform that an error has occurred (Throw the exception)
3. Receive the error information (Catch the exception)
4. Take corrective actions (Handle the exception)
Error handling code consists of two segments, one to detect errors and to
throw exceptions and the other to catch exceptions and take appropriate
actions.
While writing programs, we must check for places in the program where
an exception could be generated. Some common exceptionsare listed in
Table 4.1
Core JAVA Table 4.1 Common java Exceptions

Exception Type Cause of Exception


ArithmeticException It is caused by math errors such as
division by zero
ArrayIndexOutOfBoundsException Caused by bad array indexes
ArrayStoreException Caused when a program tries to
store the wrong type of data in an
Array
FileNotFoundException Caused by an attempt to access a
nonexistent file
IOException Caused by general I/O failures, such
as inability to read from a file
NullPointerException Caused by referencing a null object
NumberFormatException Caused when a conversion between
strings and number fails
OutOfMemoryException Caused when there’s not enough
memory to allocate a new object
SecurityException Caused when an applet tries to
perform an action not allowed by
the browser’s security setting
StackOverflowException Caused when the system runs out of
stack space
StringIndexOutOfBoundsException Caused when a program attempts to
access a nonexistent character
position in a string.

4.4 SYNTAX OF EXCEPTION HANDLING CODE


The basic concepts of Exception handling are throwing an exception and
catching it. This is illustrated in Fig. 4.1

Fig 4.1 Exception handling mechanism


Java uses a keyword try to preface a block of code that is likely to cause Exception Handling
an error condition and “throw” an exception.The catch block is added
immediately after the try block. A catch block “catches” the exception
“thrown” by the try block and handles it appropriately.
…………………….
…………………….
try
{
statement ; //generates an exception

}
catch (Exception- type e)
{
statement ; //processes the exception

}
………………………..
………………………..
The try block can have one or more statements that could generate an
exception. If any one statement generates an exception, the remaining
statements in the try block are skipped and execution jumps to the catch
block that is placed immediately next to the try block.
The catch block can have one or more statements that are necessary to
process the exception. Every try statement should be followed by at least
one catch statement; otherwise compilation error will occur.
The catch statement works like a method definition. A single parameter,
which is reference to the exception object is thrown (by the try block). If
the catch parameter matches with the type of exception object, then the
exception is caught and statements in the catch block will be executed.
Otherwise, the exception is not caught, and the default exception handler
will cause the execution to terminate.
Program 4.3 illustrates the use of try and catch blocks to handle an
arithmetic exception. Note that program 4.3 is a modified version of
Program 4.2.
Core JAVA
Program 4.3 Using try and catch for exception handling
class Error3
{
public static void main(String[] args)
{
int x = 10;
int y = 5;
int z = 5;
try
{
inta = x/(y-z); //Exception here

}
catch(ArithmeticException e)
{
System.out.println("Division by zero");
}
int b = x/(y+z);
System.out.println("b=" +y);

Program 4.3 displays the following output:

Note that the program did not stop when an exception is caused inside try
block. Exception is caught by catch block and it prints the error message,
and then continues the execution, as if nothing has happened. Compare
with the output of Program 4.2 which did not give the value of y.
Program 4.4 shows another example of using exception handling
mechanism.
Program 4.4 Example of ArrayIndexOutOfBoundsException Exception Handling
class TryCatchExample
{

public static void main(String[] args)


{
try
{
int arr[]= {1,3,5,7};
System.out.println(arr[4]); //may throw exception
}
catch(ArrayIndexOutOfBoundsException e) // handling an array
exception
{
System.out.println("Array index doesnt exist");
}

}
Output:

In this program we have array which contains 4 elements i.e arr[0], arr[1],
arr[2], arr[3]. We are printing arr[4] which doesn’t exist in the array list.
Hence ArrayIndexOutOfBoundsException is caused by try block and
caught by catch block.

4.5 MULTIPLE CATCH STATEMENTS


It is possible to have more than one catch statement in the catch block as
illustrate below:
………………….
…………………...
try
{
statement; //generates an exception
}
Core JAVA catch (Exception- Type-1 e)
{
statement; // processes exception type 1
}
catch (Exception- Type-2 e)
{
statement; // processes exception type 2
}
catch (Exception- Type-3e)
{
statement; // processes exception type N
}
………………………………
………………………………
When an exception in a try block is generated, the Java treats the multiple
catch statements like cases in a switch statement. The first statement
whose parameter matches with the exception object will be executed, and
the remaining statements will get skipped.
Note that Java does not require any processing of the exception at all. We
can simply have a catch statement with an empty block to avoid program
abortion.
Example:
catch (Exception e);
Here, the catch statement simply ends with a semicolon, which does
nothing. This statement will catch an exception and then ignore it.
Program 4.5 Using multiple catch blocks
class MultipleCatchBlock
{
public static void main(String[] args)
{
try
{
int a[]=new int[5];

System.out.println(a[10]); //doesnt exist


}
catch(ArrayIndexOutOfBoundsException e) Exception Handling
{
System.out.println("ArrayIndexOutOfBounds Exception
occurs");
}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs");
}
System.out.println("rest of the code");
}
}
Program 4.5 uses a chain of catch blocks and, when run, produces the
following output:

Note that the array element a [10] does not exist because array a is defined
to have only five elements, a[0], a[1], a[2], a[3], a[4]. Therefore, the index
10 is outside the array boundary thus causing the block
catch (ArrayIndexOutofBoundsException e)
to catch and handle the error. Remaining catch blocks are skipped.

4.6 USING FINALLY STATEMENT


Java supports finally statement that can be used to handle an exception
that is not caught by any of the previous catch statements. finally block
can be used handle any exception generated within a try block. It can be
added immediately after the try block or after the last catch block shown
as follows:
try try
{ {
…………… ……………
…………… ……………
} }
Core JAVA Finally catch(……)
{ {
…………… ……………
………….. …………….
} }
catch (……)
{
……………
…………….
}
.
.
.
finally
{
……………
…………..
}

When a finally block is defined, it is guaranteed to execute, regardless of


whether an exception is thrown or not. As a result, we can use it to
perform operations such as closing files and releasing system resources.
In Program 4.5, we may include the laststatements inside a finally block as
shown below:
Program 4.6 Using finally blocks
class FinallyBlock
{
public static void main(String[] args)
{
try
{
int a[] = new int[5];
System.out.println(a[10]); //doesnt exist
}
catch(ArrayIndexOutOfBoundsException e) Exception Handling

{
System.out.println("ArrayIndexOutOfBounds Exception occurs");

}
catch(ArithmeticException e)
{
System.out.println("Arithmetic Exception occurs");
}
catch(Exception e)
{
System.out.println("Parent Exception occurs");
}
finally
{
System.out.println("rest of the code");
}
}
}
This will produce the same output.

4.7 THROWING OUR OWN EXCEPTIONS


The Java throw keyword is used to throw an exception explicitly.
We specify the exception object which is to be thrown. The Exception has
some message with it that provides the error description.We can do this by
using the keyword throw as follows:
throw newThrowable_subclass;
Examples:
throw new ArithmeticException( );
throw new NumberFormatException( );
Core JAVA In Program 4.6, we have created validate method that takes integer value
as a parameter. If the age is less than 18, we are throwing the
ArithmeticException otherwise print a message welcome to vote.

Program 4.6 Throwing our own exception


class TestThrow
{
public static void validate(int age) //validate(age=10)
{
if(age<18) //10<18
{
//throw Arithmetic exception if not eligible to vote
throw new ArithmeticException("not eligible for voting");

}
else
{
System.out.println("You are eligible for voting");
}
}
public static void main(String args[])
{
validate(10); //calling the function
System.out.println("Rest of the code...");
}
}
A run of Program 4.6 produces:

Program 4.7 Java throws keyword

import java.io.*;
class Main1
{ Exception Handling

// declaring the type of exception


public static void findFile() throws IOException
{
// code that may generate IOException
File newFile = new File("test.txt");
FileInputStream stream = new FileInputStream(newFile);
}
public static void main(String[] args)
{
try
{
findFile();
}
catch (IOException e)
{
System.out.println(e);
}
}}
Output:

Program 4.8 Throwing our own exception


import java.lang.Exception;
class MyException extends Exception
{
MyException(String message)
{
super(message);
}
}
Core JAVA class OwnException
{
public static void main (String args[])
{
int x = 5, y = 1000;
try
{
float z = (float) x / (float) y;
if(z < 0.01)
{
throw new MyException("Number is too small");
}
}
catch(MyException e)
{
System.out.println("Caught my exception");
System.out.println(e.getMessage());
}
finally
{
System.out.println("I am always here");
}
}
}
Output:

The object e which contains the error message “Number is too small” is
caught by the catch block which then display’s the message using the
getMessage() method.
Note that Program 4.8 also illustrates the use of finally block. The last
line of output is produced by the finally block.
4.8 USING EXCEPTION FOR DEBUGGING Exception Handling

As we have seen, the exception-handling mechanism can be used to hide


errors from rest of the program. It is possible that the programmers may
misuse this technique for hiding errors rather than debugging the code.
Exception handling mechanism can be effectively used to locate the type
and place of errors. Once we identify an error, we must try to find out why
these errors occurred before we coverup them with exception handlers.

4.9 SUMMARY
A good program does not produce unexpected results. We should
incorporate features that could check for potential problem spots in
programs and guard against program failures. Exceptions in Java must be
handled carefully to avoid any program failures.
In this chapter we have discussed the following:
✓ What exceptions are
✓ try,catch and finally block
✓ How to catch and handle different types of exceptions.
✓ How to throw system exceptions

4.10 TEXTBOOK(S):
1) Herbert Schildt, Java The Complete Reference, Ninth Edition,
McGraw-Hill Education, 2014

4.11 ADDITIONAL REFERENCE(S):


1) E. Balagurusamy, Programming with Java, Tata McGraw-Hill
Education India, 2014
2) Programming in JAVA, 2nd Ed, Sachin Malhotra & Saurabh
Choudhary, Oxford Press

4.12 QUESTIONS:

1) What is Exception? Explain the types of exceptions.


2) What is error? Explain the types of error.
3) How the exceptions are handled in Java?

❖❖❖❖
MULTITHREADING
Unit Structure
5.1 Introduction

5.2 Creating threads

5.3 Extending the thread Class

5.4 Stopping and Blocking a thread

5.6 Life Cycle of A thread

5.6 Using thread Methods


5.7 Synchronization in Java

5.8 Summary
5.9 Textbook
5.10 Additional Reference(s)

5.11 Questions

5.1 INTRODUCTION
Those who are familiar with the modern operating systems (Windows 10)
may recognize that they can execute several programs simultaneously.
This ability is known as multitasking. In system's terminology, it is called
multithreading.
Multithreading is a conceptual programming paradigm where a program
(process) is divided into two or more subprograms (processes), which can
be implemented in parallel. This is similar to dividing one task into
subtasks and assigning them to different people for execution
independently and simultaneously. For example, one subprogram can
display an animation on the screen while another may build the next
animation to be displayed.
In most computers, there is only a single processor and therefore, in
reality, the processor does only one thing at a time. However, the
processor switches between the processes so fast that it appears to human
beings that all of them are being executed simultaneously. Java programs
that we have seen and discussed so far contain only a single sequential
flow of control. This is what happens when we execute a normal program.
The program begins, runs through a sequence of executions, and finally
ends. At any given point of time, there is only one statement under
execution.
A thread is similar to a program that has a single flow of control. It has a
Multithreading
beginning, a body, and an end, and executes commands sequentially. All
main programs in our earlier (previous chapters) examples can be called
single-threaded programs. Every program will have at least one thread as
shown in Fig. 5.1

Fig. 5.1 Single-threaded program

A unique property of Java is its support for multithreading. That


is, Java enables us to use multiple flows of control in developing
programs. Each flow of control may be thought of as a separate tiny
program (or module) known as a thread that runs in parallel with each
other as shown in Figure 5.2.

A program that contains multiple flows of control is known as


multithreaded program. Fig. 5.2 illustrates a Java program with four
threads, one main and two others.The main method module is main thread,
which is designed to create and start the other two threads, namely Thread
A, Thread B.
Core JAVA

Fig. 5.2 A Multithreaded program

Once initiated by the main thread, the threads A, B run concurrently and
share the resources jointly. It is like people living in joint families and
sharing certain resources among all of them. Since threads in Java are
subprograms of a main application program and share the same memory
space, they are known as lightweight threads or lightweight processes.
It is important to remember that 'threads running in parallel' does not
really mean that they are running at the same time. Since all the threads
are running on a single processor, the flow of execution is shared between
the threads. The Java interpreter handles the switching of control between
the threads in such a way that it appears they are running concurrently.
Multithreading is a powerful programming tool that makes Java distinctly
different from its fellow programming languages. Multithreading enables
programmers to do multiple things at same time. They can divide a long
program (containing operations that are conceptually concurrent) into
threads and execute them in parallel. For example, we can send print
command into the background and continue to perform some other task in
the foreground. This approach would considerably improve the speed of
our programs.
Any application we are working on that requires two or more things to be
done at the same time is probably a best one for use of threads.

5.2 CREATING THREADS


Creating threads in Java is simple. Threads are implemented in the form of
objects that contain a method called run(). The run() method is the heart
and soul of any thread. It makes up the entire body of a thread and is the
only method in which the thread's behaviour can be implemented. A Multithreading
typical run() method would appear as follows:
public void run( )

{
……………………..
……………………..
(statements for implementing thread)
……………………….
……………………….
}
The run( ) method should be invoked by an object of the concerned
thread. This can be achieved by creating the thread and initiating it with
the help of another thread method called start().
A new thread can be created in two ways.
1. By creating a thread class:
Define a class that extends Thread class and override its run( ) method
with the code required by the thread.

2. By converting a class to a thread:


Define a class that implements Runnable interface. The Runnable interface
has only one method, run( ), that is to be defined in the method with the
code to be executed by the thread.

The approach to be used depends on class which we have created, and


what it requires. If it needs to extend another class, then we have no choice
but to implement the Runnable interface, since Java classes cannot have
two super classes.

5.3 EXTENDING THE THREAD CLASS


We can make our class runnable as a thread by extending the class
java.lang.Thread. This gives us access to all the thread methods directly.
It includes the following steps:
1. Declare the class as extending the Thread class.
2. Implement the run() method that is responsible for executing the
sequence of code that the thread will execute.
3. Create a thread object and call the start() method to initiate the thread
execution.
Core JAVA
❖ Declaring the Class
The Thread class can be extended as follows:

class TestThread extends Thread


{
..........
..........
..........
}
Now have a new type of thread TestThread.

❖ Implementing the run( ) Method


The run( ) method has been inherited by the class TestThread. We must
override this method in order to implement the code to be executed by our
thread. The basic implementation of run() is as follows:
public void run( )

{
……………………..
……………………. //Thread code here
………………………
………………………
}
When we start any new thread, Java calls the thread's run( ) method, so it
is the run ( ) where all the action takes place.
❖ Starting New Thread
To create and run an instance of our thread class, we will write:
TestThread t1 = new TestThread();

t1.start( ); // invokes run( ) method


The first line instantiates a new object of class TestThread. Note that this
statement just creates the object. The thread that will run this object is not
yet running. The thread is in a newborn state.
The second line calls the start ( ) method causing the thread to move into
the runnable state. Then, the Java runtime will schedule the thread to run
by invoking its run ( ) method. Now. the thread is in the running state.
❖ An Example of Using the Thread Class Multithreading

Program 5.1 illustrates the use of Thread class for creating and running
threads in an application. In program we have created two threads A and B
for undertaking two different tasks. The main method in the ThreadTest1
class also constitutes another thread which we may call the "main thread".
The main thread dies at the end of its main method. However, before it
dies. it creates and starts other two threads A, B.
We can start a thread as follows:
A t1 = new A();
t1.start();
Immediately after the thread A is started, there will be two threads running
in the program: the main thread and the thread A.
The start() method returns back to the main thread immediately after
invoking the run( ) method, thus the allowing the main thread to start the
thread B.
Program 5.1 Creating threads using the thread class
class A extends Thread
{
public void run()
{
for (int i =1; i<=5; i++)
{
System.out.println("Thread A: i=" +i);
}
System.out.println("Exit from A");
}
}
class B extends Thread
{
public void run()
{
for (int j =1; j<=5; j++)
{
System.out.println("Thread B: j=" +j);
}
Core JAVA System.out.println("Exit from B");
}
}
class Threadtest1
{
public static void main(String args[])
{
A t1 = new A();
B t2 = new B();
t1.start(); //start first thread
t2.start(); //start second thread
}
}
Output:
First run

Second run
Third run
Multithreading

By the time the main thread has reached the end of its main method, there
are a total of three separate threads running in parallel.
We have simply initiated two new threads and started them. We did not
hold on to them further. They are running concurrently on their own. Note
that the outputs from the threads are not sequential. They do not follow
any specific order.
They are running independently of one another and each executes
whenever it has a chance. Remember, once the threads started. We cannot
decide with certainty the order in which they may execute statements.
Note a second run and third run has a different output sequence.

5.4 STOPPING AND BLOCKING A THREAD


Stopping a Thread
Whenever we want to stop a thread from running further, we may do so by
calling stop( )method, like:
aThread.stop( );
This statement causes the thread to move to the dead state. A thread will
also move to the dead state automatically when it reaches the end of its
method. The stop( ) method may be used when the premature death of a
thread is desired.
Blocking a Thread
A thread can also be suspended temporarily or blocked from entering
into the runnable and subsequently running state by using either of the
following thread methods:
sleep( ) / / blocked for a specified time

suspend( ) / / blocked until further orders


wait ( ) / / blocked until certain condition occurs

These methods cause the thread to go into the blocked (or not-runnable)
state.
Core JAVA The thread will return to the runnable state when the specified time is
elapsed in the case of sleep( ).
The resume() method is invoked in the case of suspend( ), and the notify
( ) method is called in the case of wait( ).

5.5 LIFE CYCLE OF A THREAD


During the lifetime of a thread, it can enter many states. It includes:
1. Newborn state
2. Runnable state
3. Running state
4. Blocked state
5. Dead state
A thread is always in one of these five states. It can move from one state
to another via a variety of ways as shown in Fig. 5.3.

Fig. 5.3 State transition diagram of a thread

Newborn State
When we create a thread object, the thread is born and is said to be in
newborn state. The thread is not yet scheduled for running. At this state,
we can do only one of the following things with it:
✓ We can schedule it for running using start() method.
✓ We can kill it using stop() method.
If scheduled, it moves to the runnable state (Fig. 5.4). If we attempt to use
any other method at this stage, an exception will be thrown.
Multithreading

Fig. 5.4 scheduling a newborn thread


Runnable State
The runnable state means that the thread is ready for execution and is
waiting for the availability of the processor, i.e the thread has joined the
queue of threads that are waiting for execution. If all threads have equal
priority, then they are given time slots for execution in first- come, first-
serve manner. The thread that relinquishes control joins the queue at the
end and again waits for its turn.
However, if we want a thread to relinquish control to another thread of
equal priority before its turn comes, we can do so by using the yield()
method. (Fig. 5.5)

Fig. 5.5 Relinquishing control using yield() method


Running State
Running means that the processor has given its time to the thread for its
execution. The thread runs until it relinquishes control on its own or it is
pre-empted by a higher priority thread.
A running thread may relinquish its control in one of the following
situations.
1) It has been suspended by using suspend() method. A suspended
thread can be revived by using the resume() method.
This approach is useful when we do not want to kill a thread but want to
suspend it for some time due to certain reason.
Core JAVA

Fig. 5.6 Relinquishing control using suspend() method

2) It has been made to sleep. We can make a thread to sleep for a


specified time period using the method sleep (time) where time is in
milliseconds.
It means that the thread is out of the queue during this time period. As
soon as this time period is elapsed, the thread re-enters the runnable state.

Fig. 5.7 Relinquishing control using sleep() method

3) It has been told to wait until some event occurs. It is done using the
wait() method.
The thread can be scheduled to run again using the notify() method.

Fig. 5.8 Relinquishing control using wait() method


Blocked State Multithreading

A thread is said to be in blocked state when it is prevented from entering


the runnable state and subsequently the running state.
It happens when the thread is suspended, sleeping or waiting in order to
satisfy certain requirements.
A blocked thread is considered “not runnable” but it is not dead and
therefore fully qualified to run again.
Dead State
Every thread has a life cycle. A running thread ends its life when it
completes executing its run () method. It is a natural death.
However, we can kill it by sending the stop message to it at any state thus
causing a premature death. A thread can be killed as soon as it is born, or
while it is running, or even when it is in “not runnable” (blocked)
condition.

5.6 USING THREAD METHODS


Thread class methods can be used to control the behaviour of a thread.
We have already used the methods start() and run() in program 5.1. There
are methods that can move a thread from one state to another.
Program 5.2 illustrates the use of yield(), sleep(), and stop() methods.

Program 5.2 Use of yield(), stop(), and sleep() methods


class A extends Thread

{
public void run()
{

for (int i =1; i<=5; i++)


{
if(i==1) yield();

System.out.println("Thread A: i=" +i);


}
System.out.println("Exit from A");
}
}
class B extends Thread
Core JAVA {
public void run()
{
for (int k =1; k<=5; k++)
{
System.out.println("Thread B: k=" +k);

if(k==1)
try
{
sleep(2000);
}
catch(Exception e)
{
}
}

System.out.println("Exit from B");


}
}
class ThreadMethods
{
public static void main(String args[])
{
A t1 = new A();
B t2 = new B();
System.out.println("Start thread A");
t1.start();
System.out.println("Start thread B");
t2.start();
System.out.println("End of main thread"); Multithreading

}
}
Output:

Program 5.2 uses the yield() method in thread A at the iteration i=1.
Therefore, the thread A, although started first, has relinquished its control
to the thread B.
The thread B started sleeping after executing for loop only once.
When it woke up (after 2000 milliseconds), the other thread has already
completed its runs and therefore was running alone.
The main thread died much earlier than the other two threads.

5.7 SYNCHRONIZATION IN JAVA


So far, we have seen threads that use their own data and methods provided
inside their run()methods. What happens when they try to use data and
methods outside themselves? In such situations, they may compete for the
same resources and may lead to serious problems.
For example, one thread may try to read a record from a file while another
is still writing to the same file. Depending on the situation, we may get
strange results.
Java provides a way to overcome this problem using a technique known as
synchronization.
In case of Java, the keyword synchronized helps to solve such problems
by keeping a watch on such locations. For example, the method that will
read information from a file and the method that will update the same file
may be declared as synchronized.
Core JAVA Example:
synchronized void update()
{
………………….
…………………. //code here is synchronized
……………………
}
When we declare a method synchronized, Java creates a “monitor” and
hands it over to the thread that calls the method first time. As long as the
thread is holding the monitor, no other thread can enter the synchronized
section of the code. A monitor is like a key and the thread that holds the
key can only open the lock.
It is also possible to mark a block of code as synchronized as shown
below:
synchronized (lock-object)

{
…………………… //code here is synchronized
……………………
}
Whenever a thread completes its work of using synchronized method (or
block of code), it will hand over the monitor to the next thread that is
ready to use the same resource.
A deadlock situation may occur when two or more threads are waiting to
gain control of a resource. Due to some reason, the condition on which the
waiting threads rely on to gain control does not happen.
For example, assume that the thread X must access Method1 before it can
release Method2, but the thread Y cannot release Method1 until it gets
hold of Method2. Because these are mutually exclusive conditions, a
deadlock occurs. The code below illustrates this:
Thread X
synchronized method2 ()
{
synchronized method1()
{
……………………
…………………… Multithreading
}
}
Thread Y
synchronized method1 ()
{
synchronized method2 ()
{
……………………
……………………
}
}
5.8 SUMMARY
A thread is a single line of execution within a program. Multiple threads
can run concurrently in any single program.
A thread is created either by sub classing the Thread class or
implementing the Runnable interface. Careful application of
multithreading will considerably improve the execution speed of Java
programs.

5.9 TEXTBOOK
Herbert Schildt, Java The Complete Reference, Ninth Edition, McGraw-
Hill Education, 2014

5.10 ADDITIONAL REFERENCE(S)


1. E. Balagurusamy, Programming with Java, Tata McGraw-Hill
Education India, 2014
2. Programming in JAVA, 2nd Ed, Sachin Malhotra & Saurabh
Choudhary, Oxford Press

5.11 QUESTIONS
1. What is thread? Explain the life cycle of thread.
2. Explain the synchronization of thread.
3. Write a java program to implement the concept of thread.

❖❖❖❖

You might also like