You are on page 1of 21

Module - 4

Multi-Threaded Programming
Terminologies
 Process: A program under execution is called as process.
 Thread: A smallest component of a process that can be executed independently.
OR
A thread is an independent path of execution within a single program.
 Multi-Threaded Programming: A process with two or more threads is being
executed concurrently.
 Process based multi-tasking: It allows executing two or more processes

.in
concurrently. Example: Browsing the internet, editing PowerPoint presentation
concurrently.
 Thread based multi-tasking: It allows executing two or more threads
concurrently. Example: Assume a program will be having 3 methods namely A(),

C() concurrently.
Difference between Process and Thread
ac
B(), C(). Say thread T1, executes A(), thread T2 executes B(), Thread T3 executes
tu
Process Thread
.v

Program under execution is called as Component or part of a program that can


process be executed independently is called as
thread
w

Each process has unique address space Threads shares same address space
w

Inter process communication is Inter thread communication is easier


expensive and limited and inexpensive
w

Processes are heavy weight Threads are light weight

Java cannot handle process based multi- Java can handle thread based multi-
tasking tasking

 Thread Priorities:
o It is an integer number assigned to threads.
o A priority indicates how one thread should be treated over other threads.
o Thread priority is used to decide when to switch from one running thread
to other.
o A method of switching from one running thread or process to other thread
or process respectively is known as context switching.
 When context switching happens
o A thread can voluntarily relinquish control i.e. running thread releases
the CPU to run highest priority thread voluntarily or A thread can be pre-
empted by a higher priority thread.
 Main Thread
o When Java program starts execution, one thread begins immediately, that
thread is termed as main thread.
o Main thread is required for two reasons, namely

.in
 This thread spawns child threads
 Performs various shutdown activities before completing execution.
o Main thread is a last thread to complete execution.
Thread Life Cycle
ac
There are five states a thread can possess in its life time, namely
tu
1. New: Thread is in new state, when an instance of thread class is created and
before calling start( ) method.
2. Runnable: A thread is in runnable state after invocation of start() method,
.v

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
w

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

5. Terminated: A thread is in terminated or dead state when its run() method


exits.
w
.in
ac
tu
Thread Class
The Thread class contains following constructors and functions.
.v

Constructors
w

Thread( )
w

Thread(String Name)

Thread(Runnable R)
w

Thread(Runnable R, String Name)

Functions Description
Calls run( ) method to begin thread
public void start( )
execution
Contains code that is to be executed by
public void run( )
thread
Sends currently executing thread to
public void sleep( )
sleep mode
public void sleep(long milliSecs) Sends currently executing thread to
sleep mode for specified amount of time
public int getPriority( ) Returns priority of the Thread
public void setPriority(int priority) Changes priority of current thread
public String getName( ) Returns name of current thread
Returns reference of the currently
public Thread currentThread( )
executing thread
public int getId( ) Returns ID of the thread
Returns true, if thread is alive
public boolean isAlive( ) Returns false, if thread has completed
execution
public void join( ) Waits for thread to die
Waits for thread to die for specified milli
public void join(long ms)
seconds

.in
How to create Thread in Java?
There are two ways to create threads in Java, namely
1. By extending Thread class
2. By implementing Runnable interface
Creating Thread By extending Thread class
ac
tu
Follow below steps to create thread by extending Thread class,
1. Extend Sub class by Thread class
.v

2. Override run( ) method of Thread class inside sub class


3. Create sub-class object
w

4. Call start( ) method by sub-class object


Below program demonstrates the creation of thread.
w

/* ThreadDemo.java */
class thrExample extends Thread{
w

public void run(){


System.out.println("---- Execution by Child
Thread ----");
}
}
public class ThreadDemo {
public static void main(String [] args){
thrExample t1 = new thrExample();
thrExample t2 = new thrExample();
t1.start();
t2.start();
}
}
Output:
---- Execution by Child Thread ----
---- Execution by Child Thread ----
Below program demonstrates various functions of Thread class.
/* ThreadDemo.java */
class thrExample extends Thread{
thrExample(String thName){

.in
super(thName);
}
public void run(){

ac
System.out.println("---- New Thread ----");
System.out.println("Current Thread : " +getName());
System.out.println("Thread Priority: " +getPriority());
tu
System.out.println("Thread Status : " +isAlive());
System.out.println("Thread Id : " +getId());
.v

}
}
w

public class ThreadDemo {


public static void main(String [] args){
w

thrExample t1 = new thrExample("ONE");


thrExample t2 = new thrExample("TWO");
w

System.out.println("Current Thread : "


+Thread.currentThread());
t1.start();
t2.start();
}
}
Output:
Current Thread : Thread[main,5,main]
---- New Thread ----
Current Thread : TWO
Thread Priority: 5
Thread Status : true
Thread Id : 9
---- New Thread ----
Current Thread : ONE
Thread Priority: 5
Thread Status : true
Thread Id : 8
Creating Thread by Implementing Runnable Interface
Follow below steps to create thread by implementing Runnable Interface

.in
1. Create sub class by implementing Runnable interface
2. Override run( ) method inside the subclass
3. Create Thread object by calling Thread constructor and pass object of sub

ac
class as parameter for which Thread should be created
4. Call start( ) method by Thread object
Below program demonstrates creation of thread by implementing
tu
Runnable interface.
/* ThreadRunn.java */
.v

public class threadRun implements Runnable{


public void run()
w

{
System.out.println("Thread is executing using runnable
w

interface");
}
w

public static void main(String[] args) {


threadRun tr = new threadRun();
Thread t = new Thread(tr);
Thread t1 = new Thread(tr);
Thread t2 = new Thread(tr);
t.start();
t1.start();
t2.start();
}
}
Output:
Thread is executing using runnable interface
Thread is executing using runnable interface
Thread is executing using runnable interface
How to create multiple threads
Below program demonstrates the creation of multiple threads

/* thExample.java */

class thExample implements Runnable{


Thread t;

.in
thExample(String thName){
t = new Thread(this, thName);
System.out.println("New Thread ----" +t.getName() +"----
is created");

}
t.start(); ac
tu
public void run(){
System.out.println("Thread --- " +t.getName() +" ---is
.v

executing");
}
w

}
public class threadRunMul {
w

public static void main(String [] args){


new thExample("ONE");
w

new thExample("TWO");
}
}
Output:
New Thread ----ONE---- is created
New Thread ----TWO---- is created
Thread --- TWO ---is executing
Thread --- ONE ---is executing
isAlive( ) and join( )
1. Function belongs to : Thread class
Function Name: isAlive( )
Task: Checks whether the thread has finished execution
Prototype: final boolean isAlive( )
Return value: true, if thread upon which it is called is still running
false, if thread upon which it is called is completed execution
2. Function belongs to : Thread class
Function Name: join( )
Task: waits until the thread on which it is called terminates
Prototype: final void join( ) or final void join(long milliSecs)

.in
Return value: No return value
Below program demonstrates above two functions

class thRun implements Runnable{


Thread t;
thRun(String thName){
ac
tu
t = new Thread(this, thName);
t.start();
.v

}
public void run(){
w

try{
for(int i = 1; i <= 2; i++){
w

System.out.println("Thread " +t.getName() +" "


+i);
w

Thread.sleep(1000);
}
}catch(InterruptedException e){
System.out.println(t.getName() +" is Interrupted");
}
System.out.println(t.getName() +" is exiting");
}
}
public class thMulRun {
public static void main(String [] args){
thRun t1 = new thRun("ONE");
thRun t2 = new thRun("TWO");
System.out.println("Main Thread Started");
System.out.println("Thread ONE is alive "
+t1.t.isAlive());
System.out.println("Thread ONE is alive "
+t2.t.isAlive());
try{
System.out.println("Waiting for Child threads to
finish");
t1.t.join();

.in
t2.t.join();
}catch(InterruptedException e){
System.out.println("Main thread Interrupted");
}
ac
System.out.println("Main Thread Completed");
}
tu
}
Output:
.v

Main Thread Started


Thread ONE is alive true
w

Thread ONE is alive true


Waiting for child threads to finish
w

Thread TWO 1
Thread ONE 1
w

Thread TWO 2
Thread ONE 2
TWO is exiting
ONE is exiting
Main Thread Completed
Thread Priorities
 Thread priorities are used by scheduler to decide when each thread should be
allowed to run.
Functions Associated with Thread Priorities
1. Function belongs to : Thread class
Function Name: setPriority( )
Task: Changes priority of current thread
Prototype: public void setPriority( )
Return value: No return value
2. Function belongs to : Thread class
Function Name: getName( )

.in
Task: Fetches the name of current thread on which it is called
Prototype: public String getName( )
Return value: Returns name of the thread
3. Function belongs to : Thread class
Function Name: setName( )
ac
tu
Task: Sets name to thread on which it is called
Prototype: public void setName(String Name)
.v

Return value: No return value


4. Function belongs to : Thread class
w

Function Name: getId( )


Task: Fetches the Id of thread on which it is called
w

Prototype: public int getId( )


Return value: Returns integer number
w

Below program demonstrates various functions of Thread class.


/* ThreadDemo.java */
class thrExample extends Thread{
thrExample(String thName){
super(thName);
}
public void run(){
System.out.println("---- New Thread ----");
System.out.println("Current Thread : " +getName());
System.out.println("Thread Priority: " +getPriority());
System.out.println("Thread Status : " +isAlive());
System.out.println("Thread Id : " +getId());
}
}
public class ThreadDemo {
public static void main(String [] args){
thrExample t1 = new thrExample("ONE");
thrExample t2 = new thrExample("TWO");
System.out.println("Current Thread : "
+Thread.currentThread());
t1.start();

.in
t2.start();
}
}
Output: ac
Current Thread : Thread[main,5,main]
tu
---- New Thread ----
Current Thread : TWO
.v

Thread Priority: 5
Thread Status : true
w

Thread Id : 9
---- New Thread ----
w

Current Thread : ONE


Thread Priority: 5
w

Thread Status : true


Thread Id : 8
Synchronization
 When two or more threads needs to access shared data, then data inconsistency
problem arises. Imagine a scenario,
o Thread T1 is writing data into a file numbers.txt.
o Thread T2 is reading data from a file numbers.txt.
 In this scenario, when T1 is writing, if T2 reads the file concurrently, data may
not be correct. Hence, when one thread is using shared resource, other threads
should not be allowed to use until first thread completes the task.
 In Java, synchronization is achieved using monitor or lock.
 Each object has unique lock associated with them.
 A thread that needs to access shared resource, first acquires the lock, as soon as
completes the execution, thread automatically releases the lock.

.in
 To synchronize the function, prefix the keyword synchronized in function
definition
 Example: In the below program, thread executes the function “disp( )”, program
without synchronization.
Synchronized Methods ac
/* ThreadSyncOne.java (Without Synchronization)*/
tu
class First{
void disp(){
.v

System.out.println("Good");
try {
w

Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.println("Thread Interrupted");
w

}
System.out.println("Morning");
w

}
}
class Two extends Thread{
First f = new First();
Two(First f1){
f = f1;
}
public void run(){
f.disp();
}
}
public class ThreadSyncOne {
public static void main(String [] args){
First f = new First();
Two t1 = new Two(f);
Two t2 = new Two(f);
t1.start();
t2.start();
}
}
Output:
Good
Good

.in
Morning
Morning

ac
Above Program using synchronized keyword
/* ThreadSyncOne.java (Using Synchronization)*/
class First{
tu
void disp(){
System.out.println("Good");
.v

try {
Thread.sleep(500);
} catch (InterruptedException ex) {
w

System.out.println("Thread Interrupted");
}
w

System.out.println("Morning");
}
w

}
class Two extends Thread{
First f = new First();
Two(First f1){
f = f1;
}
public void run(){
f.disp();
}
}
public class ThreadSyncOne {
public static void main(String [] args){
First f = new First();
Two t1 = new Two(f);
Two t2 = new Two(f);
t1.start();
t2.start();
}
}
Output:
Good
Morning

.in
Good
Morning
Synchronized Blocks

ac
Synchronized blocks are required when,
o Synchronize access to objects of a class that was not designed for multi-
threading.
o Class does not use synchronized methods.
tu
 During above conditions, synchronized blocks can be used.
 synchronized(Object){
.v

//Statements to be synchronized
}
Where, Object  is a reference to the object being referenced.
w

Below, program demonstrates the use of synchronized block.


/* ThreadSyncBlock.java*/
w

class Callme{
void disp(){
w

System.out.println("Good");
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
System.out.println("Thread Interrupted");
}
System.out.println("Morning");
}
}

class Caller implements Runnable{


Callme c;
Thread t;
public Caller(Callme thrObj){
c = thrObj;
t = new Thread(this);
t.start();
}

public void run(){


synchronized(c){
c.disp();
}
}
}
public class ThreadSyncBlock {
public static void main(String [] args){
Callme cmObj = new Callme();
Caller c1 = new Caller(cmObj);

.in
Caller c2 = new Caller(cmObj);
}
}
Output:
Good
Morning
ac
tu
Good
Morning
.v

Inter Thread Communication


 It is mechanism that allows two or more synchronized threads to
w

communicate with each other.


 In Java, Inter thread communication is achieved using
w

o wait( )
o notify( )
w

o notifyAll( )
wait( )
 The wait method releases the lock of current thread and moves it to waiting
state. Thread will awake, when other thread calls notify( ) or notifyAll( )
method for the object, or till specified time elapses.
 Prototype:
1. public final void wait( ) throws InterruptedException
2. public final void wait(long timeout) throws InterruptedException
notify( )
 Notifies the thread in waiting state on the same object to wake up.
 Prototype:
1. public final void notify( )
notifyAll( )
 Notifies all threads in waiting state on the same object to wake up.
 Prototype:
1. public final void notifyAll( )
Process of Inter Thread Communication

.in
ac
tu
.v

Working of Threads with respect to above diagram


w

1. Threads enter to acquire lock.


2. Lock is acquired by on thread.
w

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

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.
Difference between wait( ) and sleep( )

wait( ) sleep( )
sleep( ) method does not releases the
wait( ) method releases the lock
lock
Method of object class Method of Thread class
Non-static method Static method
Should be notified by notify( ) or
wakes up after specified time
notifyAll( )
Below program demonstrates the withdrawal and depositing money using inter
thread communication.
Scenario:
 Available balance in the account is 5000.

.in
 Say, Thread T1, tries to withdraw an amount of 10000. Since, balance is less,
thread cannot withdraw. It calls wait( ) and goes to waiting state until
another thread deposits money and wakes up this thread.


method and wakes up thread T1.
ac
Say, Thread T2, deposits 10000, now balance is 15000. Now, T2 calls notify( )

Now, T1 resumes with its execution.


tu
/* threadWaitNotify */
class Customer{
int amount = 5000;
.v

synchronized void withdraw(int withAmount){


w

System.out.println("About to withdraw");
w

if(amount < withAmount){


System.out.println("No Sufficient Funds");
try{
w

wait();
}catch(Exception e){
System.out.println("Waiting to deposit, but
done");
}
amount = amount - withAmount;
System.out.println("Withdrawl of " +withAmount +"
completed");
}
}
synchronized void deposit(int depAmount){
System.out.println("Depositing Amount");
amount = amount + depAmount;
System.out.println("Depositing " +depAmount);
notify();
}
}

public class ThreadWaitNotify {


public static void main(String [] args){
final Customer c = new Customer();
new Thread(){
public void run(){
c.withdraw(10000);

.in
}
}.start();
new Thread(){
public void run(){

}
c.deposit(10000);

}.start();
ac
tu
}
}
.v

Producer – Consumer Problem


 In computing, the producer–consumer problem (also known as the bounded-
w

buffer problem) is a classic example of a multi-process synchronization


problem. The problem describes two processes, the producer and the
consumer, which share a common, fixed-size buffer used as a queue.
w

 The producer’s job is to generate data, put it into the buffer, and start again.
 At the same time, the consumer is consuming the data (i.e. removing it from
w

the buffer), one piece at a time.


Problem
 To make sure that the producer won’t try to add data into the buffer if it’s full
and that the consumer won’t try to remove data from an empty buffer.
Solution
 The producer is to either go to sleep or discard data if the buffer is full. The
next time the consumer removes an item from the buffer, it notifies the
producer, who starts to fill the buffer again. In the same way, the consumer
can go to sleep if it finds the buffer to be empty. The next time the producer
puts data into the buffer, it wakes up the sleeping consumer.
An inadequate solution could result in a deadlock where both processes are waiting
to be awakened.
Below program demonstrates the Producer – Consumer problem using Linked List.
/* ThreadExample */
import java.util.LinkedList;

public class Threadexample


{
public static void main(String[] args)
throws InterruptedException
{
// Object of a class that has both produce()
// and consume() methods
final PC pc = new PC();

.in
// Create producer thread
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
ac
tu
pc.produce();
}
catch(InterruptedException e)
.v

{
e.printStackTrace();
}
w

}
});
w

// Create consumer thread


Thread t2 = new Thread(new Runnable()
{
w

@Override
public void run()
{
try
{
pc.consume();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
});
// Start both threads
t1.start();
t2.start();

// t1 finishes before t2
t1.join();
t2.join();
}

// This class has a list, producer (adds items to list


// and consumber (removes items).
public static class PC
{
// Create a list shared by producer and consumer
// Size of list is 2.

.in
LinkedList<Integer> list = new LinkedList<>();
int capacity = 2;

// Function called by producer thread

{
int value = 0;
while (true)
ac
public void produce() throws InterruptedException
tu
{
synchronized (this)
{
.v

// producer thread waits while list


// is full
while (list.size()==capacity)
w

wait();

System.out.println("Producer produced-"
w

+ value);
w

// to insert the jobs in the list


list.add(value++);

// notifies the consumer thread that


// now it can start consuming
notify();

// makes the working of program easier


// to understand
Thread.sleep(1000);
}
}
}
// Function called by consumer thread
public void consume() throws InterruptedException
{
while (true)
{
synchronized (this)
{
// consumer thread waits while list
// is empty
while (list.size()==0)
wait();

//to retrive the ifrst job in the list


int val = list.removeFirst();

.in
System.out.println("Consumer consumed-"
+ val);

// Wake up producer thread


notify();
ac
// and sleep
Thread.sleep(1000);
tu
}
}
}
.v

}
}
Output:
w

Producer produced-0
Producer produced-1
w

Consumer consumed-0
Consumer consumed-1
w

Producer produced-2
Consumer consumed-2