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

Unit-11 Multithreaded Programming

The document provides an overview of multithreaded programming in Java, covering the Java Thread Model, thread creation, synchronization, and the thread lifecycle. It explains the differences between process-based and thread-based multitasking, the importance of thread priorities, and the methods to define and manage threads. Additionally, it highlights the main thread's role and best practices for implementing threads using the Runnable interface.

Uploaded by

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

Unit-11 Multithreaded Programming

The document provides an overview of multithreaded programming in Java, covering the Java Thread Model, thread creation, synchronization, and the thread lifecycle. It explains the differences between process-based and thread-based multitasking, the importance of thread priorities, and the methods to define and manage threads. Additionally, it highlights the main thread's role and best practices for implementing threads using the Runnable interface.

Uploaded by

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

Multithreaded

programming
Unit :11
Content

● The Java Thread Model

● Thread priorities, synchronization, messaging, the thread class and the runnable interface

● The main thread

● Creating a thread: implementing runnable, extending thread

● Creating multiple threads: using isAlive() and join()

● Thread priorities

● Synchronization: using synchronized methods, the synchronized statement


● 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.
● Thus, multithreading is a specialized form of multitasking.
● A thread is a light-weight smallest part of a process that can run concurrently with
the other parts (other threads) of the same process. Threads are independent
because they all have separate path of execution.
○ A thread is a lightweight subprocess, the smallest unit of processing. It has 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.
● The process of executing multiple threads simultaneously is known as
multithreading.
● As shown in the above 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.

● The main purpose of multithreading is to provide simultaneous execution of two or


more parts of a program to maximum utilize the CPU time. A multithreaded program
contains two or more parts that can run concurrently. Each such part of a program
called thread.

● In Multithreaded environment, programs that are benefited from multithreading,


utilize the maximum CPU time so that the idle time can be kept to minimum.
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)


○ Thread-based Multitasking (Multithreading)
Process-based Multitasking (Multiprocessing)

● Executing several tasks simultaneously where each task is a separate independent


process such type of multitasking is called process based multitasking.

Example:

● While typing a java program in the editor we can able to listen mp3 audio songs at
the same time we can download a file from the net all these tasks are independent
of each other and executing simultaneously and hence it is Process based
multitasking.
● This type of multitasking is best suitable at "os level".
Thread based multitasking:

● Executing several tasks simultaneously where each task is a separate independent


part of the same program, is called Thread based multitasking.
● And each independent part is called a "Thread".
● This type of multitasking is best suitable for "programatic level”.
The main important application areas of multithreading are:

● To implement multimedia graphics.


● To develop animations.
● To develop video games etc.
● To develop web and application servers

Note:

Whether it is process based or Thread based the main objective of multitasking is to


improve performance of the system by reducing response time.
Life cycle of a Thread (Thread States)

● A thread goes through various stages in its life cycle.


● Threads exist in several states. Here is a general description.
● 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 halts 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.
New (Born) State

● The thread is in new state if you create an instance of Thread class but before the invocation of
start() method.
● When the thread instance is created, it will be in “New” state.

Runnable (Ready) State

● The thread is in runnable state after invocation of start() method, but the thread scheduler has
not selected it to be the running thread.
● When the thread is started, it is called “Runnable” state.

Running State

● The thread is in running state if the thread scheduler has selected it.
● When the thread is running, it is called “Running” state
Waiting (Blocked) State

● This is the state when the thread is still alive, but is currently not eligible to run.
● When the thread is put on hold or it is waiting for the other thread to complete, then that state
will be known as “waiting” state.

Terminated (Dead) State

● A thread is in terminated or dead state when its run() method exits.


● When the thread is dead, it will be known as “terminated” state
The Main Thread

● When a Java program starts up, one thread begins running immediately. This is
usually called the main thread of your program, because it is the one that is
executed when your 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.
The ways to define instantiate and start a new Thread:

We can define a Thread in the following 2 ways.

1. By extending Thread class.


2. By implementing Runnable interface.
Defining a Thread by extending "Thread class"

● We need to override the run() of Thread class.


● This process is known as defining a thread
class ThreadDemo extends Thread{

public void run(){

for(int i=0;i<10;i++){ Executed by child thread

System.out.println("Child thread");

}
class ThreadDemo{
public static void main(String[] args){
MyThread t=new MyThread();//Instantiation of a Thread
t.start();//starting of a Thread
for(int i=0;i<5;i++){ Executed by main thread
System.out.println("main thread");
}
}
}
Output

It varies.
Case 1:Thread Scheduler

● It is the part of JVM

● It is responsible to schedule threads.

● If multiple Threads are waiting to execute then which Thread will execute 1st is
decided by "Thread Scheduler" which is part of JVM.

● Which algorithm or behavior followed by Thread Scheduler we can't expect exactly it


is the JVM vendor dependent hence in multithreading examples we can't expect
exact execution order and exact output.
Case 2: Difference between t.start() and t.run() methods

● What happens when we call t.start() and t.run() methods directly.


● In the case of t.start() a new Thread will be created which is responsible for the
execution of run() method.
● But in the case of t.run() no new Thread will be created and run() method will be
executed just like a normal method by the main Thread.
● In the above program if we are replacing t.start() with t.run() the following is the
output.
Let’s see example.
Case 3: importance of Thread class start()
method.
● For every Thread the required mandatory activities like registering the Thread with
Thread Scheduler will takes care by Thread class start() method and programmer is
responsible just to define the job of the Thread inside run() method.
● That is start() method acts as best assistant to the programmer.

Example:

start(){

1. Register Thread with Thread Scheduler

2. All other mandatory low level activities.

3. Invoke or calling run() method.

● We can conclude that without executing Thread class start() method there is no
chance of starting a new Thread in java. Due to this start() is considered as heart of
multithreading.
Case 4: If we are not overriding run() method:
● If we are not overriding run() method then Thread class run() method will be
executed which has empty implementation and hence we won't get any output.
● It is highly recommended to override run() method. Otherwise don't go for
multithreading concept.
● Example:
Case 5: Overloading of run() method.
● We can overload run() method but Thread class start() method always invokes no argument run() method the
other overload run() methods we have to call explicitly then only it will be executed just like normal method.
Example

class MyThread extends Thread{

public void run(){

System.out.println("no arg method");

public void run(int i){

System.out.println("int arg method");

}
Case 6: overriding of start() method:
● If we override start() method then our start() method will be executed just like a
normal method call and no new Thread will be started.
● Example:
Note : It is never recommended to override start() method.
Case 7: Start method calling
Case 8: life cycle of the Thread:
● Once we created a Thread object then the Thread is said to be in new state or born
state.

● Once we call start() method then the Thread will be entered into Ready or Runnable
state.

● If Thread Scheduler allocates CPU then the Thread will be entered into running state.

● Once run() method completes then the Thread will entered into dead state.
Case 9:
● After starting a Thread we are not allowed to restart the same Thread once again
otherwise we will get runtime exception saying "IllegalThreadStateException".

Example:

MyThread t=new MyThread();

t.start();//valid

;;;;;;;;

t.start();//we will get R.E saying: IllegalThreadStateException


Defining a Thread by implementing Runnable
interface:
● We can define a Thread even by implementing Runnable interface also.
● Runnable interface present in java.lang.pkg and contains only one method run().
class MyRunnable implements RUnnable{

public void run(){

for(int i =0; i<10;i++){

System.out.println(“Child Thread”);

}
class ThreadDemo{
public static void main(String[] args){
MyRunnable r=new MyRunnable();
Thread t=new Thread(r);//here r is a Target Runnable
t.start();
for(int i=0;i<10;i++){
System.out.println("main thread");
}
}
}
Output:

We can't expect exact output but there are several possible outputs.
Case study:

MyRunnable r=new MyRunnable();

Thread t1=new Thread();

Thread t2=new Thread(r);


Case 1: t1.start():
● A new Thread will be created which is responsible for the execution of Thread class
run()method.
● Output:

main thread

main thread

main thread

main thread

main thread
Case 2: t1.run():
● No new Thread will be created but Thread class run() method will be executed just
like a normal method call.
● Output:

main thread

main thread

main thread

main thread

main thread
Case 3: t2.start():
● New Thread will be created which is responsible for the execution of MyRunnable
run() method.
Case 4: t2.run():
● No new Thread will be created and MyRunnable run() method will be executed just
like a normal method call.
● Output:
● child Thread
● child Thread
● child Thread
● child Thread
● child Thread
● main thread
● main thread
● main thread
● main thread
● main thread
Case 5: r.start()
● We will get compile time error saying start()method is not available in MyRunnable
class.
Case 6: r.run():
● No new Thread will be created and MyRunnable class run() method will be executed
just like a normal method call.
Best approach to define a Thread
● Among the 2 ways of defining a Thread, implements Runnable approach is always
recommended.

● In the 1st approach our class should always extends Thread class there is no
chance of extending any other class hence we are missing the benefits of
inheritance.

● But in the 2nd approach while implementing Runnable interface we can extend
some other class also. Hence implements Runnable mechanism is recommended to
define a Thread.
Thread class constructors

● Thread t=new Thread();

● Thread t=new Thread(Runnable r);

● Thread t=new Thread(String name);

● Thread t=new Thread(Runnable r,String name);

● Thread t=new Thread(ThreadGroup g,String name);

● Thread t=new Thread(ThreadGroup g,Runnable r);

● Thread t=new Thread(ThreadGroup g,Runnable r,String name);

● Thread t=new Thread(ThreadGroup g,Runnable r,String name,long stackSize)


Getting and setting name of a Thread
● Every Thread in java has some name it may be provided explicitly by the programmer
or automatically generated by JVM.
● Thread class defines the following methods to get and set name of a Thread.

Methods:

● public final String getName()


● public final void setName(String name)

Note:

● We can get current executing Thread object reference by calling currentThread( )


Example

class MyThread extends Thread{}


class ThreadDemo{
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());//main
MyThread t=new MyThread();
System.out.println(t.getName());//Thread-0
Thread.currentThread().setName("Dashain");
System.out.println(Thread.currentThread().getName());
}
}
Example
Thread Priorities
● Every Thread in java has some priority it may be default priority generated by JVM
(or) explicitly provided by the programmer.

● The valid range of Thread priorities is 1 to 10[but not 0 to 10] where 1 is the least
priority and 10 is highest priority.

● Thread class defines the following constants to represent some standard priorities.

○ Thread. MIN_PRIORITY----------1

○ Thread. MAX_PRIORITY----------10

○ Thread. NORM_PRIORITY--------5

● There are no constants like

○ Thread.LOW_PRIORITY,

○ Thread.HIGH_PRIORITY
● Thread scheduler uses these priorities while allocating CPU.

● The Thread which is having highest priority will get chance for 1st execution.

● If 2 Threads having the same priority then we can't expect exact execution order it
depends on Thread scheduler whose behavior is vendor dependent.

● We can get and set the priority of a Thread by using the following methods.

● public final int getPriority()

● public final void setPriority(int newPriority);//the allowed values are 1 to 10

● The allowed values are 1 to 10 otherwise we will get runtime exception saying
"IllegalArgumentException"
Default priority

● The default priority only for the main Thread is 5. But for all the remaining Threads the default priority will be
inheriting from parent to child. That is whatever the priority parent has by default the same priority will be for the
child also.
Example 1

class MyThread extends Thread{}

class ThreadPriorityDemo{

public static void main(String[] args){

System.out.println(Thread.currentThread().getPriority());//5

Thread.currentThread().setPriority(9);

MyThread t=new MyThread();

System.out.println(t.getPriority());//9

}
Example 2

class MyThread extends Thread{

public void run(){

for(int i=0;i<10;i++){

System.out.println("child thread");

}
class ThreadPriorityDemo{
public static void main(String[] args){
MyThread t=new MyThread();
//t.setPriority(10); //----> 1
t.start();
for(int i=0;i<10;i++){
System.out.println("main thread");
}
}
}
● If we are commenting line 1 then both main and child Threads will have the same
priority and hence we can't expect exact execution order.
● If we are not commenting line 1 then child Thread has the priority 10 and main
Thread has the priority 5 hence child Thread will get chance for execution and after
completing child Thread main Thread will get the chance.
The Methods to Prevent a Thread from
Execution
We can prevent(stop) a Thread execution by using the following methods.

● yield();
● join();
● sleep();
yield():

● yield() method causes "to pause current executing Thread for giving the chance of
remaining waiting Threads of same priority".
● If all waiting Threads have the low priority or if there is no waiting Threads then the
same Thread will be continued its execution.
● If several waiting Threads with same priority available then we can't expect exact
which Thread will get chance for execution.
● The Thread which is yielded when it get chance once again for execution is depends
on mercy of the Thread scheduler.
Method

● public static native void yield();


Diagram
Example

class MyThread extends Thread{


public void run(){
for(int i=0;i<5;i++){
Thread.yield();// line 1
System.out.println("child thread");
}
}
}
class ThreadYieldDemo{
public static void main(String[] args){
MyThread t=new MyThread();
t.start();
for(int i=0;i<5;i++){
System.out.println("main thread");
}
}
}
● If we comment line one then both the thread will execute simultaneously and the
output can varies.
● Else,in the above program child Thread is always calling yield() method and hence
main Thread will get the chance more number of times for execution.
● Hence the chance of completing the main Thread first is high.
Join()

● If a Thread wants to wait until completing some other Thread then we should go for
join() method.
● Example: If a Thread t1 executes t2.join() then t1 should go for waiting state until
completing t2.
Diagram

SLC Plus 2 Bachelor

t1 t2 t1.join t3 t2.join
Methods

● public final void join()throws InterruptedException


● public final void join(long ms) throws InterruptedException
● public final void join(long ms,int ns) throws InterruptedException
Note:

● Every join() method throws InterruptedException, which is checked exception hence


compulsory we should handle either by try catch or by throws keyword.Otherwise we
will get compiletime error.
Example

class MyThread extends Thread{


public void run(){
for(int i=0;i<5;i++){
System.out.println("Sita Thread");
try{
Thread.sleep(2000);
}catch (InterruptedException e){}
}
}
}
class ThreadJoinDemo{
public static void main(String[] args)throws InterruptedException{
MyThread t=new MyThread();
t.start();
t.join(); // Line 1
for(int i=0;i<5;i++){
System.out.println("Rama Thread");
}
}
}
● If we are commenting line 1 then both Threads will be executed simultaneously and
we can't expect exact execution order.
● Else, main Thread will wait until completing child Thread in this the output is sita
Thread 5 times followed by Rama Thread 5 times.
Note :

If main thread calls join() on child thread object and child thread called join() on main
thread object then both threads will wait for each other forever and the program will be
hanged(like deadlock if a Thread class join() method on the same thread itself then the
program will be hanged ).
Sleep()

If a Thread don't want to perform any operation for a particular amount of time then we should go for sleep() method.

● public static native void sleep(long ms) throws InterruptedException


● public static void sleep(long ms,int ns)throws InterruptedException
Diagram
Example:
class ThreadSleepDemo{
public static void main(String[] args)throws InterruptedException{
System.out.println("M");
Thread.sleep(3000);
System.out.println("E");
Thread.sleep(3000);
System.out.println("G");
Thread.sleep(3000);
System.out.println("A");
}
}
isAlive()

● The isAlive() method of thread class tests if the thread is alive.


● A thread is considered alive when the start() method of thread class has been called
and the thread is not yet dead.
● This method returns true if the thread is still running and not finished otherwise
returns false.
Method

● public final boolean isAlive()


Example
public class JavaIsAliveExp extends Thread{
public void run(){
try{
Thread.sleep(300);
System.out.println("is run() method isAlive "+Thread.currentThread().isAlive());
}catch (InterruptedException ie) { }
}public static void main(String[] args){
JavaIsAliveExp t1 = new JavaIsAliveExp();
System.out.println("before starting thread isAlive: "+t1.isAlive());
t1.start();
System.out.println("after starting thread isAlive: "+t1.isAlive());
}
}
Synchronization
● Synchronized is the keyword applicable for methods and blocks but not for classes and
variables

● If a method or block declared as the synchronized then at a time only one Thread is allow
to execute that method or block on the given object.

● The main advantage of synchronized keyword is we can resolve date inconsistency


problems.

● But the main disadvantage of synchronized keyword is it increases waiting time of the
Thread and effects performance of the system.

● Hence if there is no specific requirement then never recommended to use synchronized


keyword.

● Internally synchronization concept is implemented by using lock concept.

● Every object in java has a unique lock. Whenever we are using synchronized keyword then
only lock concept will come into the picture.
● If a Thread wants to execute any synchronized method on the given object 1st it has
to get the lock of that object. Once a Thread got the lock of that object then it's allow
to execute any synchronized method on that object. If the synchronized method
execution completes then automatically Thread releases lock.

● While a Thread executing any synchronized method the remaining Threads are not
allowed execute any synchronized method on that object simultaneously. But
remaining Threads are allowed to execute any non-synchronized method
simultaneously. [lock concept is implemented based on object but not based on
method].
Example

class Display{
public synchronized void name(String name){
for(int i=0;i<5;i++){
System.out.println(name);
}
}
}
class MyThread extends Thread{
Display d;
String name;
MyThread(Display d,String name){
this.d=d;
this.name=name;
}
public void run(){
d.name(name);
}
}
class SynchronizedDemo{
public static void main(String[] args){
Display d1=new Display();
MyThread t1=new MyThread(d1,"NCCS");
MyThread t2=new MyThread(d1,"College");
t1.start();
t2.start();
}
}
● If we are not declaring name() method as synchronized then both Threads will be
executed simultaneously and we will get irregular output.
● If we declare name()method as synchronized then the Threads will be executed one
by one that is until completing the 1st Thread the 2nd Thread will wait in this case
we will get regular output.
Case 1
Display d1=new Display();

Display d2=new Display();

MyThread t1=new MyThread(d1,"dhoni");

MyThread t2=new MyThread(d2,"yuvaraj");

t1.start();

t2.start();
● Even though we declared name() method as synchronized but we will get irregular
output in this case, because both Threads are operating on different objects.

Conclusion: If multiple threads are operating on multiple objects then there is no impact
of Syncronization.If multiple threads are operating on same java objects then syncronized
concept is required(applicable)
Synchronized block

● If very few lines of the code required synchronization then it's never recommended
to declare entire method as synchronized we have to enclose those few lines of the
code with in synchronized block.

● The main advantage of synchronized block over synchronized method is it reduces


waiting time of Thread and improves performance of the system
Example 1

● To get lock of current object


● we can declare synchronized block as follows. If Thread got lock of current object
then only it is allowed to execute this block.

Synchronized(this){

}
Example 2

● To get the lock of a particular object 'b'


● we have to declare a synchronized block as follows.If thread got lock of 'b' object
then only it is allowed to execute this block.

Synchronized(b){

}
Inter Thread communication
● wait(),
● notify(),
● notifyAll()
● Two Threads can communicate with each other by using wait(), notify() and
notifyAll() methods.

● The Thread which is required updation it has to call wait() method on the required
object then immediately the Thread will entered into waiting state.

● The Thread which is performing updation of object, it is responsible to give


notification by calling notify() method.

● After getting notification the waiting Thread will get those updations.

● wait(), notify() and notifyAll() methods are available in Object class but not in Thread
class because Thread can call these methods on any common object.
● To call wait(), notify() and notifyAll() methods compulsory the current Thread should
be owner of that object

○ i.e., current Thread should has lock of that object

○ i.e., current Thread should be in synchronized area. Hence we can call wait(),

○ notify() and notifyAll() methods only from synchronized area otherwise we will
get runtime exception saying IllegalMonitorStateException.

● Once a Thread calls wait() on the given object 1st it releases the lock of that object
immediately and entered into waiting state.

● Once a Thread calls notify() (or) notifyAll() methods it releases the lock of that
object but may not immediately.

● Except these (wait(),notify(),notifyAll()) methods there is no other place(method)


where the lock release will be happen.
● Once a Thread calls wait(), notify(), notifyAll() methods on any object then it releases
the lock of that particular object but not all locks it has.

○ public final void wait()throws InterruptedException

○ public final native void wait(long ms)throws InterruptedException

○ public final void wait(long ms,int ns)throws InterruptedException

○ public final native void notify()

○ public final void notifyAll()


Notify vs notifyAll()

● We can use notify() method to give notification for only one Thread. If multiple
Threads are waiting then only one Thread will get the chance and remaining Threads
has to wait for further notification. But which Thread will be notify(inform) we can't
expect exactly it depends on JVM.

● We can use notifyAll() method to give the notification for all waiting Threads. All
waiting Threads will be notified and will be executed one by one, because they are
required lock.
Note: On which object we are calling wait(), notify() and notifyAll() methods that
corresponding object lock we have to get but not other object locks.

You might also like