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

Unit IV - Multithreading

Uploaded by

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

Unit IV - Multithreading

Uploaded by

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

Advanced Java Programming

Unit IV

Multithreading

By
Prof. Santosh M. Sabale
Head of Computer Engg
DBATU’s Institute of Petrochemical Engineering, Lonere
After studying this chapter you will be able to
• Understand the concept of multithreading and its advantages
• Study Life cycle of thread states
• Use thread methods, assign priorities to threads
• Create and execute threads
• Write synchronized thread code
• Implement Runnable interface
Ultimately, you will be able to
Write multithreaded java programs
Introduction
• Multithreading is a Java feature that allows concurrent execution of
two or more parts of a program for maximum utilization of CPU. Each
part of such program is called a thread. So, threads are light-weight
processes within a process.

• Threads can be created by using two mechanisms :


1. Extending the Thread class
2. Implementing the Runnable Interface
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: Process-
based Multitasking (Multiprocessing) and 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.
What is Thread in java
• A thread is a lightweight sub process, 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.

• As shown in the following figure, a thread is executed inside the


process. There is context-switching between the threads. There can
be multiple processes inside the OS, and one process can have
multiple threads.
• Note: At a time one thread is executed only.
Life cycle of a Thread (Thread States)
• A thread can be in one of the five states. According to Sun, there are only 4
states in thread life cycle in java - new, runnable, non-runnable and
terminated. There is no running state.
• But for better understanding the threads, we are explaining it in the 5
states.
• The life cycle of the thread in java is controlled by JVM. The java thread
states are as follows:
1. New
2. Runnable
3. Running
4. Non-Runnable (Blocked)
5. Terminated
Thread States
1) New: The thread is in new state if you create an instance of Thread class but
before the invocation of start() method.

2) Runnable: The thread is in runnable state after invocation of start() method, but
the thread scheduler has not selected it to be the running thread.

3) Running: The thread is in running state if the thread scheduler has selected it.

4) Non-Runnable (Blocked): This is the state when the thread is still alive, but is
currently not eligible to run.

5) Terminated: A thread is in terminated or dead state when its run() method exits.
Java Thread class
Java provides Thread class to achieve thread programming. Thread
class provides constructors and methods to create and perform
operations on a thread. Thread class extends Object class and
implements Runnable interface.
Java Thread Methods
S.N Modifier and Type Method Description
.

1) void start() It is used to start the execution of the thread.


2) void run() It is used to do an action for a thread.
3) static void sleep() It sleeps a thread for the specified amount of
time.
4) static Thread currentThread() It returns a reference to the currently executing
thread object.
5) void join() It waits for a thread to die.
6) int getPriority() It returns the priority of the thread.
7) void setPriority() It changes the priority of the thread.
8) String getName() It returns the name of the thread.
9) void setName() It changes the name of the thread.
10) long getId() It returns the id of the thread.
11) boolean isAlive() It tests if the thread is alive.
12) static yield() It causes the currently executing thread object to pause
void and allow other threads to execute temporarily.
13) void suspend() It is used to suspend the thread.
14) void resume() It is used to resume the suspended thread.
15) void stop() It is used to stop the thread.
16) void destroy() It is used to destroy the thread group and all of its
subgroups.
17) boolean isDaemon() It tests if the thread is a daemon thread.
18) void setDaemon() It marks the thread as daemon or user thread.
19) void interrupt() It interrupts the thread.
20) boolean isinterrupted() It tests whether the thread has been interrupted.
21) static interrupted() It tests whether the current thread has been interrupted.
boolean
22) static int activeCount() It returns the number of active threads in
the current thread's thread group.
23) void checkAccess() It determines if the currently running thread
has permission to modify the thread.

24) static boolean holdLock() It returns true if and only if the current
thread holds the monitor lock on the
specified object.
25) static void dumpStack() It is used to print a stack trace of the current
thread to the standard error stream.

26) StackTraceElement[] getStackTrace() It returns an array of stack trace elements


representing the stack dump of the thread.

27) static int enumerate() It is used to copy every active thread's


thread group and its subgroup into the
specified array.
28) Thread.State getState() It is used to return the state of the thread.
29) ThreadGroup getThreadGroup() It is used to return the thread group to which this
thread belongs
30) String toString() It is used to return a string representation of this
thread, including the thread's name, priority, and
thread group.
31) void notify() It is used to give the notification for only one thread
which is waiting for a particular object.
32) void notifyAll() It is used to give the notification to all waiting threads
of a particular object.
33) void setContextClassLoade It sets the context ClassLoader for the Thread.
r()
34) ClassLoader getContextClassLoade It returns the context ClassLoader for the thread.
r()
35) static getDefaultUncaughtEx It returns the default handler invoked when a thread
Thread.Uncau ceptionHandler() abruptly terminates due to an uncaught exception.
ghtException
Handler
36) static void setDefaultUncaughtEx It sets the default handler invoked when a thread
ceptionHandler() abruptly terminates due to an uncaught exception.
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 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 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 method 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 what the class we are creating
requires. If it requires to extend another class, then we have no choice
but to implement Runnable interface, since Java classes cannot have
two superclasses.
Extending a Thread class
• We can make our class runnable as thread by extending the class java.lang.Thread. This
gives us access to all the thread methods directly. It includes following steps:
1. Declare the class as extending the Thread class.
2. Implmenet the run() method that is responsible for executing the sepquence of code
that the thread will execute.
3. Create a thread object and call the start ( ) method to initiate the thread execution.
Declaring the class:
Class MyThread extends Thread
{ …………..
…………...
…………….
}
• Implementing the run() method:
public void run()
{ ………..
……….. // Thread code here
………..
}
• Starting New Thread:
MyThread aThread = new MyThread(); // thread is in a new state
aThread.start(); // thread is in a runnable state

Java runtime (thread scheduler actually) will schedule the thread by


invoking run() method. Now thread is said to be in a running state.
Program: ThreadTest.java
Note: Once the thread is started, we cannot decide with certainty the order
in which they may execute statements.
• Stopping and Blocking a Thread:
aThread.stop();
• This statement causes the thread to move to the dead state. A thread will also
move to 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 or blocked from entering into
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 () // block until certain condition occurs
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().
Using Thread Methods: use of yield(), stop()
and sleep() methods
Program: ThreadMethods.java
Thread Priority
• In Java, each thread is assigned a priority, which affects the order in which it is
scheduled for running. The threads of the same priority are given equal
treatment by the Java scheduler and, therefore, they share the processor on a
first-come, first-serve basis.
• In Java, setPriority() method is used to set the priority of the method,
ThreadName.setPriority(intNumber);
The Thread class defines several priority constants:
MIN_PRIOPRITY = 1
NORM_PRIOPRITY = 5 //This is default setting of the thread
MAX_PRIOPRITY = 10
Most user-level processes should use NORM_PRIORITY, plus or minus 1.
Background tasks such as network I/O and screen repainting should use a value
very near to lower limit. We should be very cautious when trying to use very high
priority values. This may defeat the very purpose of using multithreads.
• By assigning priorities to threads, we can ensure that they are given
the attention (or lack of it) they deserve. For example, we may need
to answer an input as quickly as possible. Whenever multiple threads
are ready for execution, the Java system chooses the highest priority
thread and executes it. For a thread of a lower priority to gain control,
one of the following things should happen: (with the current thread):
1. It stops running at the end of run().
2. It is made to sleep using sleep().
3. It is told to wait using wait().
However, if another thread of a higher priority comes along, the
currently running thread will be preempted by the incoming thread
thus forcing the current thread to move to the runnable state. (Higher
priority thread always preempts the lower priority thread).
Program: ThreadPriority.java
Thread Scheduler
• Thread scheduler in java is the part of the JVM that decides which thread
should run.
• There is no guarantee that which runnable thread will be chosen to run by
the thread scheduler.
• Only one thread at a time can run in a single process.
• The thread scheduler mainly uses preemptive or time slicing scheduling to
schedule the threads.
• Difference between preemptive scheduling and time slicing:
• Under preemptive scheduling, the highest priority task executes until it enters
the waiting or dead states or a higher priority task comes into existence.
Under time slicing, a task executes for a predefined slice of time and then
reenters the pool of ready tasks. The scheduler then determines which task
should execute next, based on priority and other factors.
Thread Synchronization
• When we start two or more threads within a program, there may be a situation
when multiple threads try to access the same resource and finally they can
produce unforeseen result due to concurrency issues. For example, if multiple
threads try to write within a same file then they may corrupt the data because
one of the threads can override data or while one thread is opening the same file
at the same time another thread might be closing the same file.
• So there is a need to synchronize the action of multiple threads and make sure
that only one thread can access the resource at a given point in time. This is
implemented using a concept called monitors. Each object in Java is associated
with a monitor, which a thread can lock or unlock. Only one thread at a time may
hold a lock on a monitor.
• Java programming language provides a very handy way of creating threads and
synchronizing their task by using synchronized blocks. You keep shared resources
within this block. Following is the general form of the synchronized statement −
• Syntax
synchronized(objectidentifier) {
// Access shared variables and other shared resources
}
• Here, the objectidentifier is a reference to an object whose lock associates with
the monitor that the synchronized statement represents. Now we are going to
see two examples, where we will print a counter using two different threads.
When threads are not synchronized, they print counter value which is not in
sequence, but when we print counter by putting inside synchronized() block, then
it prints counter very much in sequence for both the threads.
• Multithreading Example without Synchronization:
• Here is a simple example which may or may not print counter value in sequence
and every time we run it, it produces a different result based on CPU availability
to a thread.
• The synchronization is mainly used to
 To prevent thread interference.
 To prevent consistency problem.

• Types of Synchronization
 Process Synchronization
 Thread Synchronization

Here, we will discuss only thread synchronization.


• Thread Synchronization
• There are two types of thread synchronization mutual exclusive and inter-thread communication.
• Mutual Exclusive
• Synchronized method.
• Synchronized block.
• static synchronization.
• Cooperation (Inter-thread communication in java)
Mutual Exclusive
Mutual Exclusive helps keep threads from interfering with one another
while sharing data. This can be done by three ways in java:
by synchronized method
by synchronized block
by static synchronization
• Concept of Lock in Java
Synchronization is built around an internal entity known as the lock or
monitor. Every object has an 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.
From Java 5 the package java.util.concurrent.locks contains several lock
implementations.
Understanding the problem without
Synchronization
• In this example, there is no synchronization, so output is inconsistent.
Let's see the example:
• Program: TestSynchronization1.java
OutPut
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.
• Program: TestSynchronization2.java
OutPut
Example of synchronized method by using
anonymous class
• In this program, we have created the two threads by anonymous
class, so less coding is required.
• Program: TestSynchronization3.java
OutPut
Java Runnable Interface
• Java runnable is an interface used to execute code on a concurrent
thread. It is an interface which is implemented by any class if we want
that the instances of that class should be executed by a thread.

• The runnable interface has an undefined method run() with void as


return type, and it takes in no arguments. The summary of the run()
method is given below:

Method Description

public This method takes in no arguments. When the object of a class implementing
void run() Runnable class is used to create a thread, then the run method is invoked in
the thread which executes separately.
• The runnable interface provides a standard set of rules for the instances of
classes which wish to execute code when they are active. The most
common use case of the Runnable interface is when we want only to
override the run method. When a thread is started by the object of any
class which is implementing Runnable, then it invokes the run method in
the separately executing thread.
• A class that implements Runnable runs on a different thread without
subclassing Thread as it instantiates a Thread instance and passes itself in
as the target. This becomes important as classes should not be subclassed
unless there is an intention of modifying or enhancing the fundamental
behavior of the class.

• Runnable class is extensively used in network programming as each thread


represents a separate flow of control. Also in multi-threaded programming,
Runnable class is used. This interface is present in java.lang package.
Implementing Runnable
• It is the easiest way to create a thread by implementing Runnable.
One can create a thread on any object by implementing Runnable. To
implement a Runnable, one has only to implement the run method.
• public void run()
• In this method, we have the code which we want to execute on a
concurrent thread. In this method, we can use variables, instantiate
classes, and perform an action like the same way the main thread
does. The thread remains until the return of this method. The run
method establishes an entry point to a new thread
How to create a thread using Runnable
interface
• To create a thread using runnable, use the following code-
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
• The thread will execute the code which is mentioned in the run()
method of the Runnable object passed in its argument.
• A simple thread example using runnable
• Program: ExampleClass.java
Thread vs. Runnable
Thread class vs Runnable interface
• There are several differences between Thread class and Runnable interface
based on their performance, memory usage, and composition.
• By extending thread, there is overhead of additional methods, i.e. they
consume excess or indirect memory, computation time, or other resources.
• Since in Java, we can only extend one class, and therefore if we extend
Thread class, then we will not be able to extend any other class. That is
why we should implement Runnable interface to create a thread.
• Runnable makes the code more flexible as, if we are extending a thread,
then our code will only be in a thread whereas, in case of runnable, one
can pass it in various executor services, or pass it to the single-threaded
environment.
• Maintenance of the code is easy if we implement the Runnable interface.
• java.lang.Runnable is an interface that is to be implemented by a class
whose instances are intended to be executed by a thread. There are two
ways to start a new Thread – Subclass Thread and implement Runnable.
There is no need of subclassing Thread when a task can be done by
overriding only run() method of Runnable.

• Steps to create a new Thread using Runnable :


1. Create a Runnable implementer and implement run() method.
2. Instantiate Thread class and pass the implementer to the Thread, Thread
has a constructor which accepts Runnable instance.
3. Invoke start() of Thread instance, start internally calls run() of the
implementer. Invoking start(), creates a new Thread which executes the code
written in run().
Calling run() directly doesn’t create and start a new Thread, it will run in the
same thread. To start a new line of execution, call start() on the thread.
• Program: RunnableDemo.java
• Output shows two active threads in the program – main thread and
Thread-0, main method is executed by the Main thread but invoking
start on RunnableImpl creates and starts a new thread – Thread-0.

• What happens when Runnable encounters an exception ?


• Runnable can’t throw checked exception but RuntimeException can
be thrown from run(). Uncaught exceptions are handled by exception
handler of the thread, if JVM can’t handle or catch exceptions, it
prints the stack trace and terminates the flow.
• Program: RunnableDemoException.java
• Output shows that Runnable can’t throw checked exceptions,
FileNotFoundException in this case, to the callers, it must handle
checked exceptions in the run() but RuntimeExceptions (thrown or
auto-generated) are handled by the JVM automatically.
END

You might also like