Thread
Thread
Multithreading in Java
Multithreading in Java is a process of executing multiple threads simultaneously.
A thread is a lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading, both
are used to achieve multitasking.
However, we use multithreading than multiprocessing because threads use a shared memory area. They don't
allocate separate memory area so saves memory, and context-switching between the threads takes less time than
process.
Java Multithreading is mostly used in games, animation, etc.
Multitasking
Multitasking is a process of executing multiple tasks simultaneously. We use multitasking to utilize the CPU.
Multitasking can be achieved in two ways:
o Process-based Multitasking (Multiprocessing)
o Thread-based Multitasking (Multithreading)
1) Process-based Multitasking (Multiprocessing)
o Each process has an address in memory. In other words, each process allocates a separate memory area.
o A process is heavyweight.
o Cost of communication between the process is high.
o Switching from one process to another requires some time for saving and loading registers, memory
maps, updating lists, etc.
2) Thread-based Multitasking (Multithreading)
o Threads share the same address space.
o A thread is lightweight.
o Cost of communication between the thread is low.
Note: At least one process is required for each thread.
1
Topic –Exception Handling
Thread in java
A thread is a lightweight subprocess, the smallest unit of processing. It is 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.
2
Topic –Exception Handling
o Runnable: A thread, that is ready to run is then moved to the runnable state. In the runnable state, the
thread may be running or may be ready to run at any given instant of time. It is the duty of the thread
scheduler to provide the thread time to run, i.e., moving the thread the running state.
A program implementing multithreading acquires a fixed slice of time to each individual thread. Each
and every thread runs for a short span of time and when that allocated time slice is over, the thread
voluntarily gives up the CPU to the other thread, so that the other threads can also run for their slice of
time. Whenever such a scenario occurs, all those threads that are willing to run, waiting for their turn to
run, lie in the runnable state. In the runnable state, there is a queue where the threads lie.
o Running: When the thread gets the CPU, it moves from the runnable to the running state. Generally, the
most common change in the state of a thread is from runnable to running and again back to runnable.
Blocked or Waiting: Whenever a thread is inactive for a span of time (not permanently) then, either the thread
is in the blocked state or is in the waiting state.
For example, a thread (let's say its name is A) may want to print some data from the printer. However, at the
same time, the other thread (let's say its name is B) is using the printer to print some data. Therefore, thread A
has to wait for thread B to use the printer. Thus, thread A is in the blocked state. A thread in the blocked state is
unable to perform any execution and thus never consume any cycle of the Central Processing Unit (CPU). Hence,
we can say that thread A remains idle until the thread scheduler reactivates thread A, which is in the waiting or
blocked state.
When the main thread invokes the join() method then, it is said that the main thread is in the waiting state. The
main thread then waits for the child threads to complete their tasks. When the child threads complete their job, a
notification is sent to the main thread, which again moves the thread from waiting to the active state.
If there are a lot of threads in the waiting or blocked state, then it is the duty of the thread scheduler to determine
which thread to choose and which one to reject, and the chosen thread is then given the opportunity to run.
Timed Waiting: Sometimes, waiting for leads to starvation. For example, a thread (its name is A) has entered
the critical section of a code and is not willing to leave that critical section. In such a scenario, another thread
(its name is B) has to wait forever, which leads to starvation. To avoid such scenario, a timed waiting state is
given to thread B. Thus, thread lies in the waiting state for a specific span of time, and not forever. A real example
of timed waiting is when we invoke the sleep() method on a specific thread. The sleep() method puts the thread
3
Topic –Exception Handling
in the timed wait state. After the time runs out, the thread wakes up and start its execution from when it has left
earlier.
Terminated: A thread reaches the termination state because of the following reasons:
o When a thread has finished its job, then it exists or terminates normally.
o Abnormal termination: It occurs when some unusual events such as an unhandled exception or
segmentation fault.
A terminated thread means the thread is no more in the system. In other words, the thread is dead, and there is
no way one can respawn (active after kill) the dead thread.
The following diagram shows the different states involved in the life cycle of a thread.
4
Topic –Exception Handling
o Thread()
o Thread(String name)
o Thread(Runnable r)
o Thread(Runnable r,String name)
Commonly used methods of Thread class:
public void run(): is used to perform action for a thread.
public void start(): starts the execution of the thread.JVM calls the run() method on the thread.
public void sleep(long miliseconds): Causes the currently executing thread to sleep (temporarily cease
execution) for the specified number of milliseconds.
public void join(): waits for a thread to die.
public void join(long miliseconds): waits for a thread to die for the specified miliseconds.
public int getPriority(): returns the priority of the thread.
public int setPriority(int priority): changes the priority of the thread.
public String getName(): returns the name of the thread.
public void setName(String name): changes the name of the thread.
public Thread currentThread(): returns the reference of currently executing thread.
public int getId(): returns the id of the thread.
public Thread.State getState(): returns the state of the thread.
public boolean isAlive(): tests if the thread is alive.
public void yield(): causes the currently executing thread object to temporarily pause and allow other threads
to execute.
public void suspend(): is used to suspend the thread(depricated).
public void resume(): is used to resume the suspended thread(depricated).
public void stop(): is used to stop the thread(depricated).
public boolean isDaemon(): tests if the thread is a daemon thread.
public void setDaemon(boolean b): marks the thread as daemon or user thread.
public void interrupt(): interrupts the thread.
public boolean isInterrupted(): tests if the thread has been interrupted.
public static boolean interrupted(): tests if the current thread has been interrupted.
5
Topic –Exception Handling
Runnable interface:
The Runnable interface should be implemented by any class whose instances are intended to be executed by a
thread. Runnable interface have only one method named run().
1. public void run(): is used to perform action for a thread.
Starting a thread:
The start() method of Thread class is used to start a newly created thread. It performs the following tasks:
o A new thread starts(with new callstack).
o The thread moves from New state to the Runnable state.
o When the thread gets a chance to execute, its target run() method will run.
6
Topic –Exception Handling
7
Topic –Exception Handling
FileName: MyThread2.java
public class MyThread2 implements Runnable
{
public void run()
{
System.out.println("Now the thread is running ...");
}
// main method
public static void main(String argvs[])
{
// creating an object of the class MyThread2
Runnable r1 = new MyThread2();
// creating an object of the class Thread using Thread(Runnable r, String name)
Thread th1 = new Thread(r1, "My new thread");
// the start() method moves the thread to the active state
th1.start();
8
Topic –Exception Handling
t1 0
t2 1
t3 2
t4 3
In the above table, we can see that Thread t1 has arrived first, then Thread t2, then t3, and at last t4, and the order
in which the threads will be processed is according to the time of arrival of threads.
Hence, Thread t1 will be processed first, and Thread t4 will be processed last.
9
Topic –Exception Handling
Time-slicing scheduling:
Usually, the First Come First Serve algorithm is non-preemptive, which is bad as it may lead to infinite blocking
(also known as starvation). To avoid that, some time-slices are provided to the threads so that after some time,
the running thread has to give up the CPU. Thus, the other waiting threads also get time to run their job.
In the above diagram, each thread is given a time slice of 2 seconds. Thus, after 2 seconds, the first thread leaves
the CPU, and the CPU is then captured by Thread2. The same process repeats for the other threads too.
10
Topic –Exception Handling
Preemptive-Priority Scheduling:
The name of the scheduling algorithm denotes that the algorithm is related to the priority of the threads.
Suppose there are multiple threads available in the runnable state. The thread scheduler picks that thread that has
the highest priority. Since the algorithm is also preemptive, therefore, time slices are also provided to the threads
to avoid starvation. Thus, after some time, even if the highest priority thread has not completed its job, it has to
release the CPU because of preemption.
Working of the Java Thread Scheduler
11
Topic –Exception Handling
Let's understand the working of the Java thread scheduler. Suppose, there are five threads that have different
arrival times and different priorities. Now, it is the responsibility of the thread scheduler to decide which thread
will get the CPU first.
The thread scheduler selects the thread that has the highest priority, and the thread begins the execution of the
job. If a thread is already in runnable state and another thread (that has higher priority) reaches in the runnable
state, then the current thread is pre-empted from the processor, and the arrived thread with higher priority gets
the CPU time.
When two threads (Thread 2 and Thread 3) having the same priorities and arrival time, the scheduling will be
decided on the basis of FCFS algorithm. Thus, the thread that arrives first gets the opportunity to execute first.
12
Topic –Exception Handling
// Thread 1
// Display the priority of above thread
// using getPriority() method
System.out.println("t1 thread priority : " + t1.getPriority());
// Thread 1
// Display the priority of above thread
System.out.println("t2 thread priority : " + t2.getPriority());
// Thread 3
System.out.println("t3 thread priority : " + t3.getPriority());
// 8
13
Topic –Exception Handling
// Main thread
// Displays the name of
// currently executing Thread
System.out.println(
"Currently Executing Thread : "+ Thread.currentThread().getName());
System.out.println(
"Main thread priority : " + Thread.currentThread().getPriority());
System.out.println(
"Main thread priority : "+ Thread.currentThread().getPriority());
}
}
Output
t1 thread priority : 5
t2 thread priority : 5
t3 thread priority : 5
t1 thread priority : 2
t2 thread priority : 5
t3 thread priority : 8
Currently Executing Thread : main
Main thread priority : 5
Main thread priority : 10
14
Topic –Exception Handling
15
Topic –Exception Handling
The following example shows how one can use the sleep() method on the custom thread.
FileName: TestSleepMethod1.java
class TestSleepMethod1 extends Thread
{
public void run()
{
for(int i=1;i<5;i++)
{
// the thread will sleep for the 500 milli seconds
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
System.out.println(e);
}
System.out.println(i);
}
}
public static void main(String args[])
{
TestSleepMethod1 t1=new TestSleepMethod1();
TestSleepMethod1 t2=new TestSleepMethod1();
t1.start();
t2.start();
}
}
Output:
1
1
2
2
3
3
4
4
16
Topic –Exception Handling
As you know well that at a time only one thread is executed. If you sleep a thread for the specified time, the
thread scheduler picks up another thread and so on.
Example of the sleep() Method in Java: When the sleeping time is -ive
The following example throws the exception IllegalArguementException when the time for sleeping is negative.
FileName: TestSleepMethod2.java
// important import statements
import java.lang.Thread;
import java.io.*;
17
Topic –Exception Handling
Synchronization in Java
Synchronization in Java threads is a mechanism used to control access to shared resources in a multi-threaded
environment. Without synchronization, when multiple threads try to modify the same shared resource
simultaneously, it can lead to inconsistent data or unpredictable behavior. Java provides synchronization to
ensure that only one thread can access a critical section (a part of the code that modifies shared resources) at a
time.
Why use Synchronization?
The synchronization is mainly used to
1. To prevent thread interference.
2. To prevent consistency problem.
Thread Synchronization
It can be achieved by using the following three ways:
1. By Using Synchronized Method
2. By Using Synchronized Block
3. By Using Static Synchronization
Concept of Lock in Java
Synchronization is built around an internal entity known as the lock or monitor. Every object has a lock
associated with it. By convention, a thread that needs consistent access to an object's fields has to acquire the
object's lock before accessing them, and then release the lock when it's done with them.
From Java 5 the package java.util.concurrent.locks contains several lock implementations.
1. Synchronized Methods: You can declare a method as synchronized using the synchronized keyword.
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock (also called
monitor lock) of the object. Other threads trying to access any synchronized method on the same object
will be blocked until the lock is released.
class Counter
{
private int count = 0;
public synchronized void increment()
{
count++;
}
public int getCount()
{
18
Topic –Exception Handling
return count;
}
}
2. Synchronized Block: Instead of synchronizing an entire method, you can synchronize only a portion of
it using a synchronized block. This can improve performance because the lock is held for a shorter period.
class Counter
{
private int count = 0;
public void increment()
{
synchronized (this)
{
count++;
}
}
public int getCount()
{
return count;
}
}
Here, this refers to the current object, and the lock is acquired only for the block of code within the synchronized
block.
3. Static Synchronization: If you declare a static method as synchronized, the lock will be on the class
object, rather than on the instance of the class.
class Counter
{
private static int count = 0;
public static synchronized void increment()
{
count++;
}
19
Topic –Exception Handling
Daemon thread
A daemon thread in Java is a special type of thread that runs in the background and performs tasks such as
garbage collection, memory management, or other housekeeping activities. Daemon threads are low-priority
threads and are designed to support non-critical tasks within the application.
One of the key characteristics of daemon threads is that they do not prevent the JVM from exiting. When all user
threads (non-daemon threads) finish executing, the JVM will terminate, regardless of whether daemon threads
are still running.
20
Topic –Exception Handling
// Start threads
t1.start(); // User thread
t2.start(); // Daemon thread
t3.start(); // User thread
}
}
Output:
This is a user thread.
This is a daemon thread.
This is a user thread.
Important Notes:
1. setDaemon(true) must be called before the thread is started. If you try to set a thread as daemon after
starting it, you will get an IllegalThreadStateException.
2. JVM exits when only daemon threads are running. If all non-daemon threads (user threads) complete,
the JVM will terminate, even if daemon threads are still running.
3. Use cases: Daemon threads are useful for tasks like monitoring, cleanup, or performing periodic
background tasks without requiring the program to wait for them to finish.
21
Topic –Exception Handling
{
System.out.println("Thread interrupted");
}
}
22