Module-3 (Part-II)
Multithreaded Programming
by:
Dr. Soumya Priyadarsini Panda
Sr. Assistant Professor
Dept. of CSE
Silicon Institute of Technology, Bhubaneswar
Multithreaded Programming
Java provides built-in support for multithreaded programming.
A multithreaded program contains two or more parts that can run
concurrently.
Each part of such a program is called a thread, and each thread defines
a separate path of execution
Example: A web browser
One thread that displays images/text
Other thread retrieve data from network
Cont…
Multithreading is a specialized form of multitasking.
There are two distinct types of multitasking: Process-based and thread-
based.
Process-based:
Allows computer to run two or more programs concurrently.
Example: Run the Java compiler at the same time using a text editor.
Thread-based:
The thread is the smallest unit of dispatchable code. i.e. a single
program can perform two or more tasks simultaneously.
Example: A text editor can format text at the same time that it is
printing
Difference between Process and Thread
Process Thread
A process is a program under Thread is a lightweight process
execution i.e an active program. that can be managed
independently by a scheduler.
Processes are heavyweight tasks Threads share the same address
that require their own separate space and cooperatively share the
address spaces. same heavyweight process.
Inter-process communication is Inter-thread communication is
expensive and limited. inexpensive
Context switching from one Context switching from one
process to another is costly. thread to the next is less costly.
Advantages of Multithreading
It doesn't block the user because threads are independent and can
perform multiple operations at the same time.
Many operations can be performed together, so it saves time.
Threads are independent, so it doesn't affect other threads if an
exception occurs in a single thread.
The Java Thread Model
The Java run-time system depends on threads for many things.
All the class libraries are designed with multithreading in mind.
In a singled-threaded environment, when a thread blocks, because it is
waiting for some resource, the entire program stops running.
The benefit of Java’s multithreading is that one thread can pause without
stopping other parts of your program.
Example:
Multithreading allows animation loops to sleep for a second between
each frame without causing the whole system to pause.
Cont…
Threads exist in several states:
A thread can be running.
It can be ready to run as soon as it gets CPU time.
A running thread can be suspended, which temporarily suspends its
activity.
A suspended thread can then be resumed, allowing it to pick up where
it left off.
A thread can be blocked when waiting for a resource.
At any time, a thread can be terminated, which halts its execution
immediately.
Once terminated, a thread cannot be resumed.
The Thread Class and the Runnable
Interface
Java’s multithreading system is built upon the Thread class, its
methods, and interface: Runnable.
Two ways to create a new thread in java,
By extending Thread class
or
By implementing the Runnable interface.
The Thread class defines several methods that help manage threads.
The Main Thread
When a Java program starts up, one thread begins running immediately.
This is called the main thread of the program.
It is the one that is executed when the program begins.
The main thread is important for two reasons:
It is the thread from which other “child” threads will be spawned.
Often, it must be the last thread to finish execution because it
performs various shutdown actions.
Cont…
Although the main thread is created automatically when the program is
started, it can be controlled through a Thread object.
To get the reference of a thread the method currentThread( ) needs to be
called which is a public static member of Thread
General form :
static Thread currentThread( )
Example:
class CurrentThreadDemo
{
public static void main(String args[])
{
Thread t = [Link]();
[Link]("Current thread: " + t);
// change the name of the thread
[Link]("My Thread");
[Link]("After name change: " + t);
Cont…
try {
for(int n = 5; n > 0; n--)
{
[Link](n);
[Link](1000); //time in milliseconds
}
}
catch (InterruptedException e)
{
[Link]("Main thread interrupted");
}
}
}
OUTPUT:
Current thread: Thread[main,5,main]
After name change: Thread[My Thread,5,main]
5
1
Cont…
When a thread reference variable is printed it displays, in order:
the name of the thread, its priority, and the name of its group.
Example: Thread [main, 5, main]
By default, the name of the main thread is main.
Its priority is 5, which is the default value, and main is also the name of
the group of threads to which this thread belongs.
A thread group is a data structure that controls the state of a collection
of threads as a whole.
Creating a Thread
Thread in Java can be created either by:
Implementing the Runnable interface
or by
Extending the Thread class.
Implementing Runnable Interface
To implement Runnable, a class need only implement a single method
called run( ), which is declared:
public void run( )
Inside run( ), the code that constitutes the new thread are defined.
The run( ) establishes the entry point for another concurrent thread of
execution within the program.
This thread will end when run( ) returns.
Cont…
Once a class is created that implements Runnable, an object of type
Thread can be instantiate from within that class.
After the new thread is created, it will not start running until the start( )
method is called.
Example
class NewThread implements Runnable
{
Thread t;
NewThread()
{
// Create a new, second thread
t = new Thread(this, "Demo Thread");
[Link]("Child thread: " + t);
[Link](); // Start the thread
}
Cont…
// This is the entry point for the second thread
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
[Link]("Child Thread: " + i);
[Link](500);
}
}
Cont…
catch (InterruptedException e)
{
[Link]("Child interrupted.");
}
[Link]("Exiting child thread.");
} //end of run method
} //end of NewThread class
Cont…
class ThreadDemo
{
public static void main(String args[])
{
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
[Link]("Main Thread: " + i);
[Link](1000);
}
}
Cont…
catch (InterruptedException e)
{
[Link]("Main thread interrupted.");
}
[Link]("Main thread exiting.");
} //end of main method
} //end of ThreadDemo class
OUTPUT:
Child thread: Thread[Demo Thread, 5, main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Your output may vary based upon the
Main Thread: 3 specific execution environment
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Extending Thread Class
A thread can be created by creating 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.
Example
class NewThread extends Thread
{
NewThread()
{
super("Demo Thread");
[Link]("Child thread: " + this);
start(); // Start the thread
}
Cont…
// This is the entry point for the second thread.
public void run()
{
try
{
for(int i = 5; i > 0; i--)
{
[Link]("Child Thread: " + i);
[Link](500);
}
}
Cont…
catch (InterruptedException e)
{
[Link]("Child interrupted.");
}
[Link]("Exiting child thread.");
} //end of run method
} // end of class NewThread
Cont…
class ExtendThread
{
public static void main(String args[])
{
new NewThread(); // create a new thread
try
{
for(int i = 5; i > 0; i--)
{
[Link]("Main Thread: " + i);
[Link](1000);
}
}
Cont…
catch (InterruptedException e)
{
[Link]("Main thread interrupted.");
}
[Link]("Main thread exiting.");
} // end of main method
} //end of class ExtendThread
Cont…
OUTPUT:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3 Your output may vary based upon the
Child Thread: 2
specific execution environment
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
Can we start a thread twice?
No. After starting a thread, it can never be started again.
If you does so, an IllegalThreadStateException is thrown.
In such case, thread will run once but for second time, it will throw
exception.
Example:
Cont…
public class TestThreadTwice1 extends Thread
{
public void run()
{
[Link]("running...");
}
public static void main(String args[])
{
TestThreadTwice1 t1=new TestThreadTwice1();
[Link]();
[Link]();
}
}
The code throws an exception.
Choosing an Approach:
Runnable Interface or Thread class ?
Thread class defines several methods that can be overridden by a
derived class.
But only run() is overridden for creation of child threads.
Classes should be extended only when they are being enhanced or
modified in some way.
So, if you will not be overriding any of Thread’s methods, it is probably
best simply to implement Runnable.
It’s the programmer’s choice to use Thread class or Runnable interface
Creating Multiple Threads
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
[Link]("New thread: " + t);
[Link](); // Start the thread
}
public void run()
{
try {
for(int i = 5; i > 0; i--)
{
[Link](name + ": " + i);
[Link](1000);
}
}
catch (InterruptedException e)
{
[Link](name + "Interrupted");
}
[Link](name + " exiting.");
}
}
class MultiThreadDemo
{
public static void main(String args[])
{
new NewThread("One"); // start threads
new NewThread("Two");
new NewThread("Three");
try {
// wait for other threads to end
[Link](10000);
}
catch (InterruptedException e)
{
[Link]("Main thread Interrupted");
}
[Link]("Main thread exiting.");
}
}
New thread: Thread[One,5,main] Output
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Three: 3
Your output may vary based upon the
Two: 3 specific execution environment
One: 2
Three: 2
Two: 2
One: 1
Three: 1
Two: 1
One exiting.
Two exiting.
Three exiting.
Main thread exiting.
Using isAlive() and join()
isAlive( ):
The isAlive() method returns true if the thread upon which it is called is
still running and returns false otherwise.
General form:
final boolean isAlive( )
join():
The join() method waits until the thread on which it is called terminates.
General form:
final void join( ) throws InterruptedException
Example
class NewThread implements Runnable
{
String name; // name of thread
Thread t;
NewThread(String threadname)
{
name = threadname;
t = new Thread(this, name);
[Link]("New thread: " + t);
[Link](); // Start the thread
}
public void run()
{
try {
for(int i = 5; i > 0; i--)
{
[Link](name + ": " + i);
[Link](1000);
}
}
catch (InterruptedException e)
{
[Link](name + " interrupted.");
}
[Link](name + " exiting.");
}
}
class DemoJoin
{
public static void main(String args[])
{
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
[Link]("Thread One is alive: "+ [Link]());
[Link]("Thread Two is alive: "+ [Link]());
[Link]("Thread Three is alive: "+ [Link]());
// wait for threads to finish
try
{
[Link]("Waiting for threads to finish.");
[Link]();
[Link]();
[Link]();
}
catch (InterruptedException e)
{
[Link]("Main thread Interrupted");
}
[Link]("Thread One is alive: "+ [Link]());
[Link]("Thread Two is alive: "+ [Link]());
[Link]("Thread Three is alive: "+ [Link]());
[Link]("Main thread exiting.");
}
}
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main] Output
New thread: Thread[Three,5,main]
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
One: 5 …
Two: 5 Two exiting.
Three: 5 Three exiting.
One: 4 One exiting.
Two: 4 Thread One is alive: false
Three: 4 Thread Two is alive: false
One: 3 Thread Three is alive: false
Two: 3 Main thread exiting.
Three: 3
One: 2
Two: 2
Three: 2
One: 1 Your output may vary based upon the
Two: 1 specific execution environment
Three: 1
…
Thread Priorities:
Java assigns to each thread a priority that determines how that thread
should be treated with respect to the others.
Thread priorities are integers that specify the relative priority of one
thread to another.
A thread’s priority is used to decide when to switch from one running
thread to the next. This is called a context switch.
To set a thread’s priority, the setPriority( ) method is used.
general form:
final void setPriority(int level)
level specifies the new priority setting for the calling thread.
Cont…
The value of level must be within the range MIN_PRIORITY and
MAX_PRIORITY.
These values ranges between 1 and 10, respectively.
To return a thread to default priority, specify NORM_PRIORITY,
which is currently 5.
The current priority of a thread can be obtained by calling the
getPriority( ) method.
Synchronization
If multiple threads need to communicate and share a common data,
some mechanism is needed to ensure that they don’t conflict with each
other.
That is, it is required to prevent one thread from writing data while
another thread is reading it.
Java has its own implicit monitor that is automatically entered when
one of the object’s synchronized methods is called.
Once a thread is inside a synchronized method, no other thread can call
any other synchronized method on the same object.
Cont…
In java synchronization can be achieved using the synchronized
keyword in two ways :
Using Synchronized Methods
Using Synchronized Statement
Using Synchronized Methods
While a thread is inside a synchronized method, all other threads that try
to call it (or any other synchronized method) on the same instance have
to wait
Example:
synchronized void call(String msg) {
……
}
Example without Synchronized method
// This program is not synchronized.
class Callme {
void call(String msg)
{
[Link]("[" + msg);
try {
[Link](1000);
}
catch(InterruptedException e) {
[Link]("Interrupted");
}
[Link]("]");
}
}
class Caller implements Runnable
{
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
[Link]();
}
public void run() {
[Link](msg);
}
}
class Synch {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
[Link]();
Output:
[Link](); Hello[Synchronized[World]
[Link](); ]
} ]
catch(InterruptedException e) {
[Link]("Interrupted");
}
}
}
Example with Synchronized method
//modify previous code
…….
class Callme
{
synchronized void call(String msg) {
....
….
}
Output:
} [Hello]
[Synchronized]
[World]
Using Synchronized Statement
The statements to be synchronized can be kept inside a synchronized
block.
Example-1:
synchronized(objRef) {
// statements to be synchronized
}
objRef is a reference to the object being synchronized.
A synchronized block ensures that a call to a synchronized method that
is a member of objRef’s class occurs only after the current thread has
successfully entered objRef’s monitor
Example-2: using synchronized in run()
// This program uses a synchronized block.
class Callme {
void call(String msg)
{
[Link]("[" + msg);
try {
[Link](1000);
} catch (InterruptedException e) {
[Link]("Interrupted");
}
[Link]("]");
}
}
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s)
{
target = targ;
msg = s;
t = new Thread(this);
[Link]();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
[Link](msg);
}
}}
class Synch1 {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synchronized");
Caller ob3 = new Caller(target, "World");
// wait for threads to end
try {
[Link]();
[Link]();
[Link]();
}
catch(InterruptedException e) {
[Link]("Interrupted");
}
}
}
Inter-thread Communication
Java provides a clean, low-cost way for two or more threads to talk to
each other, via calls to predefined methods that all objects have.
Java’s messaging system allows a thread to enter a synchronized method
on an object, and then wait there until some other thread explicitly
notifies it to come out.
Cont…
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( ) or
notifyAll( ).
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.