Multithreading
Motivation : why we need Threads ?
1. Responsiveness
2. Performance
Example of Poor Responsiveness
Suppose we have an online store web publication that
serves thousands of users.
The application stores all information about each user's purchases in a
database.
If one user makes a large purchase of multiple items, which results in
a long operation in the database and in the same time, another user is
desperate to complete his purchase.
That second user will not get any response until the web app is done
Multithreading
in responding to the first request.
Solution : We could actually serve multiple users simultaneously, but serving each
request on a different thread.
Responsiveness is particularly critical when it comes
to applications with a user interface.
Example : A good example for this can be a movie player application.
The application is showing us images, play the audio.
And in the same time, we expect that if we move the mouse or click
a button, we would get an instant feedback for our actions on the screen.
This kind of responsiveness can be achieved by using multiple threads,
Concurrency
Multithreading
Concurrency is refers to the ability of a program to execute multiple
tasks simultaneously. It enables the efficient utilization of system
resources and can improve the overall performance and
responsiveness of the application.
Java concurrency’s concepts, classes, and the interfaces used for
multithreading, such as `Thread`, `Runnable`, `Callable`, `Future`,
`ExecutorService`, and the classes in `[Link]`, are part of
the standard Java libraries
Multithreading refers to a programming technique where multiple
threads of execution exist within a single application.
Multithreading is just one way to achieve concurrency in Java.
Concurrency can also be achieved through other means, such as
multiprocessing, asynchronous programming, or event-driven
programming.
What is Thread in Java ?
Multithreading
In Java, a thread is the smallest unit of execution within a process. It is a
lightweight sub-process that allows a program to perform multiple tasks
concurrently. Threads share the same memory space and resources of the process
they belong to, enabling efficient communication and data sharing between
threads.
Not as that, we don't even need multiple cores to achieve
concurrency.
Even with one core, we can create responsive applications
by using multiple threads.
Multithreading
Multithreading
The performance back of multithreading is the ability to complete
a complex task in a fraction of the time.
It would take us more time to complete it otherwise.
Multithreading
We can finish much more work in the same period of time than
with a single thread.
And if we're running a high scale service on multiple machines, we
will
need less machines, which will also mean less expenses on
infrastructure
and more money in our pocket.
So now that we have the motivation for multithreading and we
understand the
parallelism and the concurrency concepts, which brings us the
desired responsiveness and the performance,
When we turn on our computer especial program called the operating system is
loaded from the disc into the memory.
Multithreading
The operating system takes over and provides an obstruction for us.
The application developers, and helps us interact with the hardware and the CPU.
So we can focus on developing our apps.
All our applications, such as the text editor, a web browser, or a
music player reside on a disc in a form of a file, just like any Otter
music file image or document when they use it around send application, the
operating system takes the program from the disc and creates an instance
of that application in the memory.
That instance is called a process, and it's also sometimes called
a context of an application.
Each process is completely isolated from any other process that runs on the system.
A few of the things that the process contains are the metadata, like
the process ID, the files that the application opens for reading and
When we turn on our computer especial program called the operating system is
loaded from the disc into the memory.
The operating system takes over and provides an obstruction for us.
The application developers, and helps us interact with the hardware and the CPU.
So we can focus on developing our apps.
All our applications, such as the text editor, a web browser, or a
music player reside on a disc in a form of a file, just like any Otter
music file image or document when they use it around send application, the
operating system takes the program from the disc and creates an instance
of that application in the memory.
That instance is called a process, and it's also sometimes called
a context of an application.
Each process is completely isolated from any other process that runs on the system.
A few of the things that the process contains are the metadata, like
the process ID, the files that the application opens for reading and
Multithreading
In a multithreaded obligation.
Multithreading
Each thread comes with its own stack and its own instruction
pointer, but all the rest of the components in the process are shared.
the process ID, the files that the application opens for reading and
writing the code, which is the program instructions that are going to be executed
on the CPU, the heap, which contains all the data, our application needs.
And finally, at least one thread called the main thread.
The thread contains two main things, the stack and the instruction pointer.
Context Swtich :
Multithreading
Each instance(process) has a unique process ID and may have one or more Threads.
All the threads are competing with each other to be executed in the CPU.
Multithreading
However, there is always more Thread than Core, so the OS has to run 1 Thread and stop it then
run another Thread.
The act of stopping a running thread and start a new one is called a context switch[5].
Context Switch Cost [5]:
Context switch cost is not cheap and is the price of multitasking (Concurrency)
Same as humans when we multitask. Take time to focus.
Each Thread consumes resources in the CPU and memory.
When we switch to a different Thread, we need to store the data for the current Thread and
restore data for another Thread
Thread Scheduling:
Multithreading
Thread Scheduling is the way the OS decides when to run which Thread and when to perform a context
switch. 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.
Multithreading
Multithreading
Multithreading
So how about we schedule a shorter job first in this case, our scheduling
sequence would look like this.
However, this has an opposite problem.
There are user related events coming to our system all the time.
So if we keep scheduling the shortest job first, all the time,
the longer tasks that involve computations will never be executed.
Multithreading
Thread Scheduling-Epochs:
Modern OS Linux scheduling algorithm works by dividing the CPU time into epochs. In a single epoch,
every process has a specified time quantum whose duration is computed when the epoch begins. In
general, different processes have different time quantum durations.
• Static priority: is set by the developer programmatically.
• Bonus: is adjusted by the OS in every epoch for each Thread.
• Using Dynamic Priority, the OS will give preference for interactive Threads (such as User Interface
Threads). OS will give preference to the thread that did not complete in the last epochs or did not get
enough time to run to prevent Starvation
Thread vs. Process:
Multithreading
When to prefer multithreading architecture:
Multiple processes
Multithreading
When to prefer multithreading architecture:
• When the tasks share a lot of resources since threads are much faster
to create and destroy.
• Switching between threads of the same process is much faster
(shorter context switches)
When Threads and processes are fundamental concepts in operating
systems and programming, especially in the context of concurrent and
parallel execution. While they share some similarities, they have distinct
characteristics and use cases. Here's a detailed comparison between threads
and processes:
1. Definition
Process:
o A process is an independent program in execution with its
own memory space, resources, and state.
o Each process runs in a separate memory space and is isolated
from other processes.
Thread:
o A thread is a lightweight sub-process within a process. It
shares the same memory space and resources as the parent
process and other threads within the same process.
2. Memory and Resource Usage
Process:
o Each process has its own separate memory space (code, data,
heap, and stack).
o Processes do not share memory by default, and inter-process
communication (IPC) is required for data exchange (e.g., pipes,
sockets, shared memory).
o Creating and managing processes is resource-intensive due to
the overhead of allocating separate memory and resources.
Multithreading
Thread:
o Threads within the same process share the same memory
space (code, data, and heap) but have their own stack.
o Communication between threads is faster and easier since they
share memory.
o Threads are lightweight compared to processes, as they require
fewer resources to create and manage.
3. Creation and Overhead
Process:
o Creating a process is expensive in terms of time and resources
because the operating system needs to allocate separate
memory and resources.
o Processes are independent, so a failure in one process does not
affect others.
Thread:
o Creating a thread is faster and less resource-
intensive because threads share the same memory and
resources as the parent process.
o However, threads are dependent on the parent process. If the
process terminates, all its threads also terminate.
4. Isolation and Stability
Process:
o Processes are isolated from each other. A crash or failure in one
process does not affect other processes.
o This isolation makes processes more stable and secure.
Thread:
o Threads share the same memory space, so a bug or crash in one
thread can affect other threads and the entire process.
o Threads are less isolated and require careful synchronization to
avoid issues like race conditions and deadlocks.
5. Communication
Process:
Multithreading
oInter-process communication (IPC) is required for processes to
exchange data. IPC mechanisms include:
Pipes
Sockets
Shared memory
Message queues
o IPC is slower due to the overhead of crossing process
boundaries.
Thread:
o Threads can communicate directly through shared
memory (e.g., shared variables, objects).
o Communication between threads is faster but requires
synchronization mechanisms (e.g., synchronized blocks, locks) to
avoid conflicts.
6. Concurrency and Parallelism
Process:
o Processes are suitable for coarse-grained concurrency, where
tasks are independent and require strong isolation.
o Processes can run in parallel on multi-core systems, but the
overhead of process creation and IPC can limit performance.
Thread:
o Threads are suitable for fine-grained concurrency, where
tasks need to share data and work closely together.
o Threads can run in parallel on multi-core systems, making them
ideal for tasks that require high performance and low overhead.
7. Scalability
Process:
o Processes are less scalable due to the overhead of creating and
managing multiple processes.
o However, processes are more resilient because they are
isolated.
Thread:
o Threads are more scalable because they are lightweight and
share resources.
Multithreading
o However, excessive threading can lead
to contention and synchronization overhead, reducing
performance.
8. Use Cases
Process:
o Running independent applications (e.g., a web browser and a
text editor).
o Tasks requiring strong isolation and security (e.g., sandboxing).
o Distributed systems where tasks run on different machines.
Thread:
o Tasks requiring shared data and close collaboration (e.g., GUI
applications, web servers).
o Performance-critical applications that need to leverage multi-
core CPUs (e.g., video rendering, scientific computations).
9. Examples
Process:
o Running multiple instances of a web browser (each tab or
window is a separate process).
o A database server handling multiple client connections, where
each connection is a separate process.
Thread:
o A web server handling multiple client requests using threads
(e.g., Apache Tomcat).
o A game engine using separate threads for rendering, physics,
and AI.
to prefer multi-process architecture:
• Security and stability are of higher importance than performance.
• Tasks are unrelated to each other.
Multithreading
Thread Creation :
We can define a Thread in the following 3 ways.
1. By extending Thread class.
2. By implementing Runnable interface.
3. By Using Anonymous Declarations
By extending Thread class
Multithreading
Thread class constructors:
1. Thread t=new Thread();
2. Thread t=new Thread(Runnable r);
3. Thread t=new Thread(String name);
4. Thread t=new Thread(Runnable r,String name);
5. Thread t=new Thread(ThreadGroup g,String name);
6. Thread t=new Thread(ThreadGroup g,Runnable r);
7. Thread t=new Thread(ThreadGroup g,Runnable r,String name);
8. Thread t=new Thread(ThreadGroup g,Runnable r,String name,long stackSize);
Multithreading
By implementing Runnable interface.
By Using Anonymous Declarations
Best approach to define a Thread:
Multithreading
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 Scheduler:
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
Multithreading
Thread Methods :
1. start()
2. run()
3. setName()
4. getName()
5. setPriorities()
6. isAlive()
7. join()
8. yield()
9. Wait()
10. Notify()
11. notifyAll()
12. interrupt()
13. isInterrupted()
14. interrupted()
15. currentThread()
16. sleep()
start()
This method starts the execution of the thread. It invokes the run() method on
the thread object, causing it to execute as a separate thread of execution. You can
call start() only once on a thread; calling it multiple times will throw
an IllegalStateException
run()
Multithreading
This is the entry point for the thread. The execution of the thread begins from this
method. You can override this method to define what the thread should do. If you
call run() directly, it will execute in the same thread as the caller, unlike
when start() is used
Difference between [Link]() and [Link]() methods.
In the case of [Link]() a new Thread will be created which is
responsible for the execution of run() method. But in the case of
[Link]() 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 [Link]() with [Link]() the following is the
output.
importance of Thread class start() method.
For every Thread the required mandatory activities like
registering the Thread with Thread Scheduler will takes care by
Multithreading
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.
Thread Life Cycle :
Multithreading
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.
Note : 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();
[Link]();//valid ;;;;;;;; [Link]();//we will get R.E saying:
IllegalThreadStateException
Multithreading
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:
1. public final String getName()
2. public final void setName(String name)
Note: We can get current executing Thread object reference by using
[Link]() method.
Thread Priorities
Multithreading
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.
1. Thread. MIN_PRIORITY----------1
2. Thread. MAX_PRIORITY----------10
[Link].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.
Multithreading
We can get and set the priority of a Thread by using the following
methods. 1. public final int getPriority() 2. 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"
The Methods to Prevent a Thread from Execution:
Multithreading
Interrupting a Thread:
What are Java Interrupts?
Java interrupts provide a mechanism for one thread to signal another thread
to stop its current operation.
It's a cooperative mechanism. The interrupted thread is not forced to stop
but is asked to stop and can choose whether or not to comply.
Why Interrupts Instead of a "Cancel" Method?
The Thread class lacks a direct "cancel" method.
Interrupts allow the target thread to clean up resources and leave things in a
consistent state before stopping (e.g., closing database connections, file
handles, etc.). Forcibly stopping a thread could lead to data corruption or
resource leaks.
Interrupts are co-operative mechanisms for indicating stop
signal to a thread
Interrupting a thread in Java involves setting an interrupt flag on the
target thread using the interrupt() method. This flag is a signal to the
thread that it should stop its current operation, but it does not forcibly
terminate the thread. Instead, it is up to the thread to check its
interrupt status and handle it appropriately.
Multithreading
In Java, you can interrupt a thread using the interrupt() method. When
a thread is interrupted, it receives a signal to stop what it is doing and
terminate gracefully. However, it is up to the thread to handle the
interruption appropriately by checking its interrupted status and
responding accordingly.
The 3 methods provided by the Thread class for interrupting
a thread
o public void interrupt()
public void interrupt()
This method interrupts a thread by setting its interrupted flag to true.
If the thread is sleeping or waiting, it throws an InterruptedException.
o
o public static boolean interrupted()
public static boolean interrupted()
This checks if the current thread has been interrupted and clears the interrupted flag.
If called twice, the second call returns false because it resets the flag.
o
o public boolean isInterrupted()
ublic boolean isInterrupted()
Unlike interrupted(), this method only checks the interrupt flag without clearing it.
We can prevent(stop) a Thread execution by using the following
methods.
Multithreading
1. yield();
2. join();
3. sleep();
yield():
The yield() method is used in Java to hint the task scheduler to move the currently
executing task to the Ready state and move another task or thread to the running
state. The task scheduler is free to ignore the hint. Through the yield() method, a
thread is willing to yield or relinquish its current use of the processor.
yield() method causes "to pause current executing Thread for giving the
chance of remaining waiting Threads of same priority"
2. If all waiting Threads have the low priority or if there is no waiting
Threads then the same Thread will be continued its execution.
3. If several waiting Threads with same priority available then we can't
expect exact which Thread will get chance for execution.
4. The Thread which is yielded when it get chance once again for
execution is depends on mercy of the Thread schedular
5. public static native void yield();
Multithreading
Let us suppose we have three threads, T1, T2 and T3, that need to be executed.
Thread T1 gets the processor and starts executing while the remaining threads T2 and T3 are in
the Ready state. The time required for thread T1 is 4 hours, while threads T2 and T3 take
only 2 and 4 minutes, respectively. This means threads T1 and T2 need to wait for four hours to
complete a total of 6-minute jobs. In such scenarios where one thread takes too long for its
completion, we need to have a method that allows the execution of other threads in between if
something important is pending. Java has a yield() method to provide such functionality.
Multithreading
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 [Link]() then t1 should go for waiting state until
completing t2.
Every join() method throws InterruptedException, which is checked
exception hence compulsory we should handle either by try catch or by
throws keyword.
public final void join(): This java thread join method puts the current
thread on wait until the thread on which it’s called is dead.
Multithreading
If the thread is interrupted, it throws InterruptedException.
public final synchronized void join(long millis): This java thread join
method is used to wait for the thread on which it’s called to be dead or
wait for specified milliseconds.
Since thread execution depends on OS implementation, it doesn’t
guarantee that the current thread will wait only for given time.
public final synchronized void join(long millis, int nanos): This java thread
join method is used to wait for thread to die for given milliseconds plus
nanoseconds.
Here is a simple example showing usage of Thread join methods. The goal
of the program is to make sure main is the last thread to finish and third
thread starts only when first one is dead
Sleep() method:
If a Thread don't want to perform any operation for a particular amount of time
then we should go for sleep() method.
1. public static native void sleep(long ms) throws InterruptedException
2. public static void sleep(long ms,int ns)throws InterruptedException
Multithreading
What is a Race Condition?
Happen when where several processes try to access the same
resources and modify the shared data concurrently. Thus, the
outcome of the process depends on the particular order of
execution that leads to data inconsistency. This condition can be
avoided by using the technique called Process Synchronization
which allowing only one process to enter and manipulates the
shared data in the Critical Section.
Entry Section: It is part of the process which decides which
process will enter the Critical Section.
• Critical Section: in critical section, only one process is
allowed to enter and modify the shared variable. This part of the
process ensures that only no other process can access the
resource of shared data.
• Exit Section: This process allows the other process that is
waiting in the Entry Section, to enter into the Critical Sections.
It checks that a process that after a process has finished
execution in Critical Section can be removed through this Exit
Section.
• Remainder Section: The other parts of the Code other than the
Entry Section, Critical Section, and Exit Section are known as
the Remainder Section.
Synchronization
Multithreading
1. Synchronized is the keyword applicable for methods and blocks but
not for
classes and variables.
2. 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.
3. The main advantage of synchronized keyword is we can resolve date
inconsistency problems.
4. But the main disadvantage of synchronized keyword is it increases
waiting time
of the Thread and effects performance of the system.
5. Hence if there is no specific requirement then never recommended
to use
synchronized keyword.
6. Internally synchronization concept is implemented by using lock
concept.
7. Every object in java has a unique lock. Whenever we are using
synchronized
keyword then only lock concept will come into the picture.
Multithreading
8. 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.
9. 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]
Here’s an interesting example demonstrating the use of a
synchronized method in Java multithreading. This example
Multithreading
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).
Scenario Explanation
When multiple threads operate on the same object,
synchronization is required to ensure proper data consistency.
When multiple threads operate on different objects,
synchronization has no impact because each object has its own
separate state.
Example: Bank Account Withdrawal
We have a BankAccount class where multiple users (threads) try to withdraw
money from the same or different accounts.
Case 1: Multiple threads operating on the SAME object (Synchronization
needed)
Case 2: Multiple threads operating on DIFFERENT objects (Synchronization has
no impact)
Multithreading
simulates a ticket booking system, where multiple users try
to book tickets concurrently. The bookTicket method is
synchronized to ensure that only one thread can access it at
a time, preventing inconsistent ticket counts.
Synchronized block:
1. 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.
2. The main advantage of synchronized block over synchronized method is it
reduces waiting time of Thread and improves performance of the system
Example: Synchronized Ticket Booking System
Multithreading
[Link]
rupesh-sahu/
[Link]
[Link]
multithreading-concurrency-interview-questions-answers
[Link]
information_technology/
Important_Methods_of_the_Thread_Class.pdf
[Link]