0% found this document useful (0 votes)
4 views25 pages

Threads Notes For Class of 9th August 2025

Multithreading in Java allows multiple threads to run concurrently within a single process, enhancing application responsiveness and performance, especially on multi-core processors. Key concepts include threads, processes, concurrency, and synchronization, with potential issues like race conditions and deadlocks. Java provides two main ways to implement multithreading: using the Thread class and implementing the Runnable interface, along with thread lifecycle management and priority settings.

Uploaded by

Tor Simon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views25 pages

Threads Notes For Class of 9th August 2025

Multithreading in Java allows multiple threads to run concurrently within a single process, enhancing application responsiveness and performance, especially on multi-core processors. Key concepts include threads, processes, concurrency, and synchronization, with potential issues like race conditions and deadlocks. Java provides two main ways to implement multithreading: using the Thread class and implementing the Runnable interface, along with thread lifecycle management and priority settings.

Uploaded by

Tor Simon
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

Threads

Multithreading is a powerful concept in Java that allows us to run multiple threads


concurrently within a single process. It’s crucial for developing responsive and
efficient applications, especially in today’s multi-core processor environments.

What is Multithreading?

Multithreading is a programming concept that allows a single process to execute


multiple threads concurrently. Threads are lightweight sub-processes within a
process that share the same memory space, but they can run independently. Each
thread represents a separate flow of control, making it possible to perform multiple
tasks simultaneously within a single program.

Threads are smaller units of a process, sharing the same memory space.

Threads can be thought of as independent, parallel execution paths.

Multithreading enables efficient utilization of multi-core processors.

• Threads are smaller units of a process, sharing the same memory space.

• Threads can be thought of as independent, parallel execution paths.


• Multithreading enables efficient utilization of multi-core processors.

•Improved Responsiveness: Multithreading allows applications to remain


responsive to user input, even when performing resource-intensive tasks. For
example, a text editor can continue responding to user actions while performing a
spell-check in the background.

• Enhanced Performance: Multithreaded programs can take advantage of multi-core


processors, leading to better performance. Tasks can be divided among multiple
threads, speeding up computation.

• Resource Sharing: Threads can share data and resources within the same process,
which can lead to more efficient memory usage. This can be crucial in memory-
intensive applications.

• Concurrency: Multithreading enables concurrent execution of tasks, making it


easier to manage multiple tasks simultaneously. For instance, a web server can
handle multiple client requests concurrently using threads.

Terminology and Concepts

To understand multithreading, it’s essential to grasp the following key concepts:

Thread: A thread is the smallest unit of execution within a process. Multiple threads
can exist within a single process and share the same memory space.

Process: A process is an independent program that runs in its memory space. It can
consist of one or multiple threads.

Concurrency: Concurrency refers to the execution of multiple threads in overlapping


time intervals. It allows tasks to appear as if they are executing simultaneously.

Parallelism: Parallelism involves the actual simultaneous execution of multiple


threads or processes, typically on multi-core processors. It achieves true
simultaneous execution.

Race Condition: A race condition occurs when two or more threads access shared
data concurrently, and the final outcome depends on the timing and order of
execution. It can lead to unpredictable behavior and bugs.
Synchronization: Synchronization is a mechanism used to coordinate and control
access to shared resources. It prevents race conditions by allowing only one thread
to access a resource at a time.

Deadlock: Deadlock is a situation in which two or more threads are unable to


proceed because each is waiting for the other to release a resource. It can result in a
system freeze.

Real-life Example of Java Multithreading

Suppose you are using two tasks at a time on the computer, be it using Microsoft
Word and listening to music. These two tasks are called processes. So you start
typing in Word and at the same time start music app, this is called multitasking. Now
you committed a mistake in a Word and spell check shows exception, this means
Word is a process that is broken down into sub-processes. Now if a machine is dual-
core then one process or task is been handled by one core and music is been handled
by another core.

In the above example, we come across both multiprocessing and multithreading.

These are somehow indirectly used to achieve multitasking. In this way the
mechanism of dividing the tasks is called multithreading in which every process or
task is called by a thread where a thread is responsible for when to execute, when to
stop and how long to be in a waiting state. Hence, a thread is the smallest unit of
processing whereas multitasking is a process of executing multiple tasks at a time.

The Thread Lifecycle:

Threads in Java go through various states in their lifecycle:

New: When a thread is created but not yet started.

Runnable: The thread is ready to run and is waiting for its turn to execute.

Running: The thread is actively executing its code.

Blocked/Waiting: The thread is temporarily inactive, often due to waiting for a


resource or event.

Terminated: The thread has completed execution and has been terminated.
Two Ways to Implement Multithreading

Using Thread Class

Using Runnable Interface

Method 1: Using Thread Class

Java provides Thread class to achieve programs involving threads. Some major
methods of thread class are shown.

Methods Action Performed

isDaemon() It checks whether the current thread is


daemon or not

start() It starts the execution of the thread

run() It executes the statements in the body of


this method over a thread

sleep() It is a static method that puts the thread


to sleep for a certain time been passed
as an argument to it

wait() It sets the thread back in waiting state.

notify() It gives out a notification to one thread


that is in waiting state

notifyAll() It gives out a notification to all the


thread in the waiting state
setDaemon() It set the current thread as Daemon
thread

stop() It is used to stop the execution of the


thread

resume() It is used to resume the suspended


thread

By default, threads are named thread-0, thread-1, and so on. But there is also a
method that is often used as setName() method. Also corresponding to it there is a
method getName() which returns the name of the thread be it default or settled
already by using setName() method. The syntax is as follows:

Syntax:

(a) Returning the name of the thread

public String getName() ;

(b) Changing the name of the thread

public void setName(String name);

Consider if one has to multiply all elements by 2 and there are 500 elements in an
array.
public class FirstThread extends Thread {

// run() method is called as

// soon as the thread is started

public void run()

// Print statement when the thread is called

System.out.println("First Thread is running now");

public class SecondThread extends Thread {

public void run()

System.out.println("Second Thread is running now");

public class ThreadDemo1 {

public static void main(String[] args)

// Creating a thread object of our thread class


FirstThread firstThread = new FirstThread();

SecondThread secondThread = new SecondThread();

// Getting the threads to the runnable state

// This thread will transcend from runnable to run

// as start() method will look for run() and execute

// it

firstThread.start();

// This thread will also transcend from runnable to

// run as start() method will look for run() and

// execute it

secondThread.start();

When you run the program above multiple times, the output will vary, should you
are expecting the first thread to run before the second as it was started first. Now
this is the reason:

The thread scheduler — part of your JVM and operating system — decides when
each thread gets CPU time.

It considers many factors like:

• Current CPU load


• Priority of threads
• Number of processor cores
• Internal JVM/OS scheduling strategies
Because of this, there is no guarantee that the first thread you start will be the first
to execute.

The out vary because when you start firstThread:

The JVM asks the OS to run it. The OS might immediately run it or put it in a
queue and run something else first.

When you then start secondThread, it also gets submitted to the OS scheduler.
The OS might decide: “Run secondThread now, firstThread later” (leading to
Second Thread is running now first) Or “Run firstThread now, secondThread
later” (leading to the opposite order).

Since the scheduling decision can be different each time — due to timing
differences, CPU state, and other processes running — your output can vary
between runs.

public class ThirdThread extends Thread{

public void run() {

// Print statement when the thread is called

System.out.println(" Third Thread 1 is running");

public class FourthThread extends Thread{

// Method

public void show() {

// Print statement when thread is called

System.out.println("Fourth Thread is running");


}

public class ThreadDemo2 {

public static void main(String[] args) {

// Creating a thread object of our thread class

ThirdThread thirdThread = new ThirdThread();

FourthThread fourthThread = new FourthThread();

thirdThread.start();

// This thread will now look for run() method which is absent

// Thread is simply created not runnable

fourthThread.start();

Method 2 – By Implementing the Runnable Interface

public class FifthThread implements Runnable{

public void run() {

// Iterating to get more execution of threads

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

System.out.println("Runnable Thread1");

try {

Thread.sleep(1000);

// Catch block to handle the exceptions


catch (Exception e) {

public class SixthThread implements Runnable{

public void run()

// Iterating to get more execution of threads

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

System.out.println("Runnable Thread2");

try {

Thread.sleep(1000);

catch (Exception e) {

public class ThreadDemo3 {

public static void main(String[] args)

// Creating reference of Runnable to


// the classes implementing runable

Runnable rO1 = new FifthThread();

Runnable rO2 = new SixthThread();

// Creating reference of thread class

// by passing object of Runnable in constructor of

// Thread class

Thread t1 = new Thread(rO1);

Thread t2 = new Thread(rO2);

t1.start();

t2.start();

Serial Execution using sleep

public class SerialSleep1 extends Thread{

public void show()

// Iterating to print more number of times

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

// Print statement

System.out.println("Shot");

// Making thread to sleep using sleep() method

// Try-catch block for exceptions

try {
Thread.sleep(1000);

catch (Exception e) {

public class SerialSleep2 extends Thread {

public void show()

// Iterating to print more number of times

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

// Print statement

System.out.println("Miss");

// Making thread to sleep using sleep() method

// Try-catch block for exceptions

try {

Thread.sleep(1000);

catch (Exception e) {

}
}

public class SerialDemo {

public static void main(String[] args) {

// Creating objects in the main() method

SerialSleep1 serialSleep1 = new SerialSleep1();

SerialSleep2 serialSleep2 = new SerialSleep2();

// Starting the thread objects

serialSleep1.start();

serialSleep2.start();

// Calling methods of class 1 and class 2

serialSleep1.show();

serialSleep2.show();

Parallel Execution Using Sleep

public class ParallelSleep1 extends Thread{

public void run()

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

System.out.println("Shot");

// Making thread to sleep using sleep() method

// Try catch block for exceptions

try {
Thread.sleep(1000);

catch (Exception e) {

public class ParallelSleep2 extends Thread{

public void run()

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

// Print statement

System.out.println("Miss");

// Making thread to sleep using sleep() method

// Try catch block for exceptions

try {

Thread.sleep(1000);

catch (Exception e) {

}
public class ParallelSleepDemo {

public static void main(String[] args)

// Creating objects in the main() method

ParallelSleep1 parallelSleep1 = new ParallelSleep1();

ParallelSleep2 parallelSleep2 = new ParallelSleep2();

// Starting the thread objects

// using start() method

// start() method calls the run() method

// automatically

parallelSleep1.start();

parallelSleep2.start();

Thread Priority

Notice that so far, there is no priority been set for threads for which as per the order
of execution of threads outputs will vary so do remember this drawback of
multithreading of different outputs leading to data inconsistency issues which we
will be discussing in-depth in the later part under synchronization in threads.

Priorities in Threads

Priorities in threads is a concept where each thread is having a priority which is


represented by numbers ranging from 1 to 10.

The default priority is set to 5 as excepted.


Minimum priority is set to 1.

Maximum priority is set to 10.

Here 3 constants are defined in it namely as follows:

public static int NORM_PRIORITY

public static int MIN_PRIORITY

public static int MAX_PRIORITY

No Priority

public class NoPriority extends Thread{

public void run()

System.out.println("Running Thread : " + currentThread().getName());

System.out.println("Running Thread Priority : " + currentThread().getPriority());

public class NoPriorityDemo {

public static void main(String[] args)

// Creating objects of MyThread(above class)

// in the main() method

NoPriority np1 = new NoPriority();

NoPriority np2 = new NoPriority();


// Case 1: Default Priority no setting

np1.start();

np2.start();

Norm Priority

public class NormPriority extends Thread {

public void run()

System.out.println("Running Thread : " + currentThread().getName());

System.out.println("Running Thread Priority : " + currentThread().getPriority());

public class NormPriorityDemo {

public static void main(String[] args)

// Creating objects of MyThread(above class)

// in the main() method

NormPriority np1 = new NormPriority();

NormPriority np2 = new NormPriority();

// Setting priority to thread via NORM_PRIORITY


// which set priority to 5 as default thread

np1.setPriority(Thread.NORM_PRIORITY);

np2.setPriority(Thread.NORM_PRIORITY);

// Setting default priority using

// NORM_PRIORITY

np1.start();

np2.start();

Min Priority

public class MinPriority extends Thread{

public void run()

// Printing the current running thread via getName()

// method using currentThread() method

System.out.println("Running Thread : "

+ currentThread().getName());

// Print and display the priority of current thread

// via currentThread() using getPriority() method

System.out.println("Running Thread Priority : "

+ currentThread().getPriority());
}

public class MinPriorityDemo {

public static void main(String[] args)

// Creating objects of MyThread(above class)

// in the main() method

MinPriority mp1 = new MinPriority();

MinPriority mp2 = new MinPriority();

// Setting priority to thread via NORM_PRIORITY

// which set priority to 1 as least priority thread

mp1.setPriority(Thread.MIN_PRIORITY);

mp2.setPriority(Thread.MIN_PRIORITY);

// Setting default priority using

// NORM_PRIORITY

mp1.start();

mp2.start();

Max Priority

public class MaxPriority extends Thread{

public void run()


{

// Printing the current running thread via getName()

// method using currentThread() method

System.out.println("Running Thread : "

+ currentThread().getName());

// Print and display the priority of current thread

// via currentThread() using getPriority() method

System.out.println("Running Thread Priority : "

+ currentThread().getPriority());

public class MaxPriorityDemo {

public static void main(String[] args)

// Creating objects of MyThread(above class)

// in the main() method

MaxPriority mp1 = new MaxPriority();

MaxPriority mp2 = new MaxPriority();

// Setting priority to thread via MAX_PRIORITY

// which set priority to 10 as most priority thread

mp1.setPriority(Thread.MAX_PRIORITY);

mp2.setPriority(Thread.MAX_PRIORITY);

// Setting default priority using


// MAX_PRIORITY

// Starting the threads using start() method

// which automatically invokes run() method

mp1.start();

mp2.start();

Daemon Threads

In Java, daemon threads are special types of threads that run in the background and
are typically used for tasks such as garbage collection, background maintenance, or
handling other non-essential tasks in an application. They are marked as daemon
because they do not prevent the JVM from exiting when the program finishes
executing.

Key Points about Daemon Threads:

Background Execution:

Daemon threads run in the background and do not have an essential role in the
execution of the main program. For example, the garbage collector is a daemon
thread.

Program Exit:

When all non-daemon (also called user) threads in a Java application finish
execution, the JVM will exit, even if daemon threads are still running. This means
that daemon threads do not prevent the JVM from terminating.

Creation:

You can create a daemon thread by calling the setDaemon(true) method before
starting the thread:
Priority:

Daemon threads have a lower priority compared to user threads. They exist to
provide services to user threads but will not prevent an application from exiting.

Use Cases:

Daemon threads are often used for low-priority background tasks, like monitoring
system resources, log writing, mail delivery failure (Mailer Daemons) or garbage
collection.

public class DaemonThread1 extends Thread{

public void run() {

// Checking whether the thread is daemon thread or

// not

if (Thread.currentThread().isDaemon()) {

// Print statement when Daemon thread is called

System.out.println( "I am daemon thread and I am working");

else {

// Print statement whenever users thread is

// called

System.out.println( "I am user thread and I am working");

}
public class DaemonThread1Demo {

public static void main(String[] args)

// Creating threads in the main body

DaemonThread1 dt1 = new DaemonThread1();

DaemonThread1 dt2 = new DaemonThread1();

DaemonThread1 dt3 = new DaemonThread1();

// Setting thread named 't2' as our Daemon thread

dt2.setDaemon(true);

// Starting all 3 threads using start() method

dt1.start();

dt2.start();

dt3.start();

// Now start() will automatically

// invoke run() method

public class DaemonThread2 extends Thread{

public void run()

// Checking whether the thread is daemon thread or

// not

if (Thread.currentThread().isDaemon()) {
// Print statement when Daemon thread is called

System.out.println( "I am daemon thread and I am working");

else {

// Print statement whenever users thread is

// called

System.out.println( "I am user thread and I am working");

public class DaemonThread2Demo {

public static void main(String[] args)

// Creating threads objects of above class

// in the main body

DaemonThread2 dt1 = new DaemonThread2();

DaemonThread2 dt2 = new DaemonThread2();

DaemonThread2 dt3 = new DaemonThread2();

// Starting all 3 threads using start() method

dt1.start();

dt2.start();

dt3.start();

// Now start() will automatically invoke run()


// method

// Now at last setting already running thread 't2'

// as our Daemon thread will throw an exception

dt2.setDaemon(true);

You might also like