Multithreaded Programming
Prepared by: Prof. Masooda
Dept. of ISE, SCEM
Creating a Thread
In the most general sense, creating a thread is by instantiating an
object of type Thread.
Java defines two ways in which this can be accomplished:
1. implement the Runnable interface.
2. extend the Thread class
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 2
1) Implementing Runnable :
• The easiest way to create a thread is to create a class that implements
the Runnable interface.
• Runnable abstracts a unit of executable code.
• construct a thread on any object that implements Runnable.
• To implement Runnable, a class need only implement a single method
called run(), which is declared like this:
public void run( )
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 3
• Inside run( ), define the code that constitutes the new thread.
• It is important to understand that run( ) can call other methods, use
other classes, and declare variables, just like the main thread can
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 4
public class Main implements Runnable {
public static void main(String[] args) {
Main obj = new Main();
Thread thread = new Thread(obj);
[Link]();
[Link]("This code is outside of the thread");
}
public void run() {
[Link]("This code is running in a thread");
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 5
Output
This code is running in a thread
This code is outside of the thread
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 6
• We can use sleep() method to see the thread running clearly
• Consider the code below
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 7
package pack;
public class Main implements Runnable {
public static void main(String[] args) {
Main obj = new Main();
Thread thread = new Thread(obj);
[Link]();
try {
for(int i=5;i>0;i--)
[Link]("This code is outside of the thread");
[Link](5000);
}
catch(InterruptedException e)
{
[Link]("intrupted");
}
}//close main() function
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 8
public void run() {
try {
for(int i=5;i>0;i--) {
[Link]("This code is running in a thread");
[Link](5000);
}
}
catch(InterruptedException e)
{
[Link]("intrupted");
}
}//close run()
}//close class()
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 9
Extending Thread:
• The second way to create a thread is to create a new class that
extends Thread, and then to create an instance of that class.
• The extending class must override the run( ) method, which is the
entry point for the new thread.
• It must also call start( ) to begin execution of the new thread.
• Here is the preceding program rewritten to extend Thread:
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 10
public class Main extends Thread {
public static void main(String[] args) {
Main thread = new Main();
[Link]();
[Link]("This code is outside of the thread");
}
public void run() {
[Link]("This code is running in a thread");
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 11
Output:
This code is running in a thread
This code is outside of the thread
This code is outside of the thread This code is running in a thread
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 12
Using isAlive( ) and join( )
• In java, isAlive() and join() are two different methods that are used to
check whether a thread has finished its execution or not.
• The isAlive( ) method returns true if the thread upon which it is called
is still running.
• Returns false otherwise
• But, join() method is used more commonly than isAlive().
• isAlive( ) is occasionally useful
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 13
• General form of isAlive( ) :
final boolean isAlive( )
True False
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 14
join()
• final void join( ) throws InterruptedException
• This method waits until the thread on which it is called terminates.
• Its name comes from the concept of the calling thread waiting until
the specified thread joins it.
• Additional forms of join( ) allow you to specify a maximum amount of
time that to wait for the specified thread to terminate.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 15
package pack;
public class isAliveExample extends Thread {
public void run() {
try {
[Link](3000);
} catch (InterruptedException e) {
[Link]("Interrupted exception");
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 16
public static void main(String[] args) {
isAliveExample thread = new isAliveExample();
[Link]("Thread status before starting: " +[Link]());
[Link]();
[Link]("Thread status after starting: " + [Link]());
try {
// Waiting for the thread to complete
[Link]();
}
catch (InterruptedException e) {
[Link]("Interrupted exception");
}
[Link]("Thread status after completion: " + [Link]());
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 17
Thread status before starting: false
Thread status after starting: true
Thread status after completion: false
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 18
Interthread Communication
• Java includes an elegant interprocess communication mechanism via
the wait( ), notify( ), and notifyAll( ) methods. These methods are
implemented as final methods in Object, so all classes have them. All
three methods can be called only from within a synchronized context.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 19
• wait( ) tells the calling thread to give up the monitor and go to sleep
until some other thread enters the same monitor and calls notify( ).
• notify( ) wakes up a thread that called wait( ) on the same object.
• notifyAll( ) wakes up all the threads that called wait( ) on the same
object. One of the threads will be granted access.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 20
These methods are declared within Object, as shown here:
• final void wait( ) throws InterruptedException
• final void notify( )
• final void notifyAll( )
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 21
Producer Consumer Problem:
class Q {
int val;
boolean flag=false;
synchronized int get()
{
if(!flag)
try
{
wait();
}
catch(InterruptedException e)
{
[Link]();
}
[Link]("Consumer consuming "+val);
flag=false;
notify();
return val;
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 22
synchronized void put(int val)
{
if(flag)
try
{
wait();
}
catch(InterruptedException e)
{
[Link]();
}
[Link]=val;
flag=true;
[Link]("Producer Producing "+val);
notify();
}
}
class producer extends Thread
{
Q obj;
producer(Q t)
{
obj=t;
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 23
}
public void run()
{
for(int i=0;i<10;i++)
{
[Link](i);
}
}
}
class consumer extends Thread
{
Q obj1;
consumer(Q t)
{
obj1=t;
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 24
public void run()
{
for(int i=0;i<10;i++)
{
[Link]();
}
}
}
public class PC {
public static void main(String[] args) {
Q q = new Q();
producer p=new producer(q);
consumer c=new consumer(q);
[Link]();
[Link]();
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 25
Output:-
Producer producing: 0
Consumer consuming: 0
Producer producing: 1
Consumer consuming: 1
Producer producing: 2
Consumer consuming: 2
Producer producing: 3
Consumer consuming: 3
Producer producing: 4
Consumer consuming: 4
Producer producing: 5
Consumer consuming: 5
Producer producing: 6
Consumer consuming: 6
Producer producing: 7
Consumer consuming: 7
Producer producing: 8
Consumer consuming: 8
Producer producing: 9
Consumer consuming: 9
Producer producing: 10
Consumer consuming: 10
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 26
Synchronization
• When two or more threads need access to a shared resource, they
need some way to ensure that the resource will be used by only one
thread at a time. The process by which this is achieved is called
synchronization.
• Key to synchronization is the concept called monitor (also called a
semaphore).
• Only one thread can own a monitor at a given time.
• All other threads attempting to enter the locked monitor will be
suspended until the first thread exits the monitor
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 27
Usage of Synchronization
• Synchronized Methods
• Synchronized Keyword
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 28
Synchronized Methods
synchronized return_type function_name (Parameters)
{
//statements
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 29
This is the general form of the synchronized statement:
synchronized(object) {
// statements to be synchronized
}
Here, object is a reference to the object being synchronized. A
synchronized block ensures that a call to a method that is a member of
object occurs only after the current thread has successfully entered
object’s monitor.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 30
package pack;
//Producer Consumer Problem: using synchronized keyword
class Q {
int val;
boolean flag=false;
int get()
{
if(!flag)
try
{
wait();
}
catch(InterruptedException e)
{
[Link]();
}
[Link]("Consumer consuming "+val);
flag=false;
notify();
return val;
}
void put(int val)
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 31
{
if(flag)
try
{
wait();
}
catch(InterruptedException e)
{
[Link]();
}
[Link]=val;
flag=true;
[Link]("Producer Producing "+val);
notify();
}
}
class producer extends Thread
{
Q obj;
producer(Q t)
{
obj=t;
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 32
}
public void run()
{
synchronized(obj) {
for(int i=0;i<10;i++)
{
[Link](i);
}
}}
}
class consumer extends Thread
{
Q obj1;
consumer(Q t)
{
obj1=t;
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 33
public void run()
{
synchronized(obj1) {
for(int i=0;i<10;i++)
{
[Link]();
}}
}
}
public class PC {
public static void main(String[] args) {
Q q = new Q();
producer p=new producer(q);
consumer c=new consumer(q);
[Link]();
[Link]();
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 34
Deadlock in Java
Deadlock in Java is a part of multithreading. Deadlock can occur in a
situation when a thread is waiting for an object lock, that is acquired
by another thread and second thread is waiting for an object lock that
is acquired by first thread. Since, both threads are waiting for each
other to release the lock, the condition is called deadlock.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 35
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
[Link]();
[Link]();
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 36
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
[Link]("Thread 1: Holding lock 1...");
try { [Link](10); }
catch (InterruptedException e) {[Link](“Exception raised");
}
[Link]("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
[Link]("Thread 1: Holding lock 1 & 2...");
}
}
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 37
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
[Link]("Thread 2: Holding lock 2...");
try {
[Link](10);
}
catch (InterruptedException e) {
[Link](“Exception raised");
}
[Link]("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
[Link]("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 38
Suspending, Resuming, and Stopping Threads
• final void suspend( )
• final void resume( )
suspend( ) and resume( ), which are methods defined by Thread, to
pause and restart the execution of a thread.
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 39
import [Link].*;
public class Main extends Thread {
public void run()
{
try {
//print the current thread
[Link]("Current thread is thread number " +
[Link]().getName());
}
catch (Exception e) {
[Link](e);
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 40
public static void main(String[] args) {
//1 thread created
Main t1=new Main();
//running the threads
[Link]();
//putting it to sleep for 300ms
[Link](300);
//now suspend the thread
[Link]();
[Link]("Thread is suspended");
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 41
//resume the thread
[Link]();
[Link]("Thread is Resumed");
try {
[Link]();
}
catch(Exception e)
{
[Link](e);
}
}
}
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 42
12/2/2024 Prof. Masooda, Dept. of ISE, SCEM 43