Multithreading
Running multiple programs on a single computer is known as multiprogramming.
Multithreading is part of Multi-tasking.
Java provides Thread class and Runnable interface to achieve multithreading.
Thread class contains the actual mechanism for multithreading.
Thread Class
Extending the Thread class:
class MyThread extends Thread {
@Override
public void run() {
int i = 0;
while (true) {
i++;
System.out.println(i + ". Hello");
}
}
}
public class Main {
public static void main(String[] args) {
MyThread thd = new MyThread();
thd.start();
int i = 0;
while (true) {
i++;
System.out.println(i + ". World");
}
}
}
Making Main class extend the Thread class:
public class Main extends Thread {
@Override
public void run() {
int i = 0;
while (true) {
i++;
System.out.println(i + ". Hello");
}
}
public static void main(String[] args) {
Main m = new Main();
m.start();
int i = 0;
while (true) {
i++;
System.out.println(i + ". World");
}
}
}
Runnable Interface
Implementing the Runnable interface:
class MyRunnable implements Runnable {
@Override
public void run() {
int i = 0;
while (true) {
i++;
System.out.println(i + ". Hello");
}
}
}
public class Main {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
int i = 0;
while (true) {
i++;
System.out.println(i + ". World");
}
}
}
Making Main class implement the Runnable interface:
public class Main implements Runnable {
@Override
public void run() {
int i = 0;
while (true) {
i++;
System.out.println(i + ". Hello");
}
}
public static void main(String[] args) {
Main m = new Main();
Thread t = new Thread(m);
t.start();
int i = 0;
while (true) {
i++;
System.out.println(i + ". World");
}
}
}
States of Thread
new -> ready -> running -> terminated
The First state of the thread is new, it stores the object of the thread.
When start() method is called then thread enters into the ready state, where it is ready to run.
Thread Priorities
JAVA supports thread priorities from 1-10.
The priority of default thread is always 5.
The thread with higher priority gets the more CPU time.
Higher priority is given to threads which gets the input or the data.
Multithreading features are provided by the operating systems... but in java, JVM have its own scheduler.
Methods of Thread Class
// Constructors
Thread()
Thread(Runnable r)
Thread(String name) // Gives name to the thread
Thread(Runnable r, String name)
Thread(ThreadGroup g, String name)
// Getter and Setter methods
long getId();
String getName();
int getPriority();
ThreadState getState();
THreadGroup getThreadGroup(); // to know the group to which the thread belongs
void setName(String name);
void setPriority(int p);
void setDaemon(Boolean d); // Daemon thread is a background thread with least priority and no user interaction
// e.g. Garbage Collector in Java
// Enquiry
boolean isAlive();
boolean isDaemon();
boolean isInterrupted();
// Instance methods
void interrupt(); // It will stop doing the currently doing work, e.g. stop waiting/sleeping
void join(); // If a thread has finished its job, then instead of terminating, it can wait for other threads to finish
// e.g. main() can wait until all the threads have finished
void join(long millseconds);
void run();
void start();
// Static Methods
int activeCount();
Thread currentThread(); // returns reference to current running thread
void yield(); // It can stop higher priority thread from starvating lower priority threads (And continue after the lower priority thread is finished)
void dumpstack(); // To know the contents in the stack or to know the depth of the stack.
Example
class MyThread extends Thread {
public MyThread(String name) {
// calling super class constructor i.e. Thread(String name)
super(name);
// Priority can be set in the main() also, using the Thread object
setPriority(Thread.MIN_PRIORITY);
}
public void run() {
int counter = 1;
while (true) {
System.out.println(counter);
counter++;
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(e);
}
}
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread("Thread 1");
System.out.println("Thread Id: " + t.getId());
System.out.println("Thread name: " + t.getName());
System.out.println("Thread Priority: " + t.getPriority());
System.out.println("Thread State: " + t.getState());
t.start();
System.out.println("Now, Thread State: " + t.getState());
t.interrupt();
}
}
Output:
Thread Id: 15
Thread name: Thread 1
Thread Priority: 1
Thread State: NEW
Now, Thread State: RUNNABLE
1
java.lang.InterruptedException: sleep interrupted
2
3
4
5
6
Synchronization
class MyData {
// We can synchronize a block or a complete function
public void display(String str) {
synchronized (this) {
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i));
}
}
}
// synchronized public void display(String str) {
// for (int i = 0; i < str.length(); i++) {
// System.out.print(str.charAt(i));
// }
// }
}
class MyThread1 extends Thread {
MyData d = new MyData();
public MyThread1(MyData d) {
this.d = d;
}
public void run() {
d.display("Hello World");
}
}
class MyThread2 extends Thread {
MyData d = new MyData();
public MyThread2(MyData d) {
this.d = d;
}
public void run() {
d.display("Welcome");
}
}
public class Main {
public static void main(String[] args) {
MyData data = new MyData();
MyThread1 thd1 = new MyThread1(data);
MyThread2 thd2 = new MyThread2(data);
thd2.start();
thd1.start();
}
}
The classes MyThread1 and MyThread2 access the data from the display class which is the shared object.
Example using ATM Machine
class ATM {
synchronized public void checkBalance(String name) {
System.out.print(name);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(" is checking balance");
}
synchronized public void withdraw(String name, int amount) {
System.out.print(name);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(" is withdrawing " + amount);
}
}
class Customer extends Thread {
private String name;
private int amount;
private ATM atm;
public Customer(String name, int amount, ATM atm) {
this.name = name;
this.amount = amount;
this.atm = atm;
}
public void useATM() {
atm.checkBalance(name);
atm.withdraw(name, amount);
}
public void run() {
useATM();
}
}
public class Main {
public static void main(String[] args) {
ATM atm = new ATM();
Customer c1 = new Customer("Jack", 2000, atm);
Customer c2 = new Customer("John", 2000, atm);
c1.start();
c2.start();
}
}
ATM Object is a shared resource, so we need to synchronize it.
Inter Thread Communication
Inter-Process Communication (IPC) → between processes
Inter-Thread Communication → between threads inside the same process
Inter-thread communication is a way for threads to coordinate their work so they don’t step on each other’s toes.
Typical scenario:
One thread produces data (producer)
Another thread consumes data (consumer)
They share the same object
These methods must be called inside synchronized blocks or methods.
When a thread cannot proceed because a required condition is not met, it calls wait() and releases the lock.
When another thread changes the condition, it calls notify() or notifyAll() to wake waiting threads.
notify vs notifyAll
That’s why conditions must always be checked in a while loop, not if.
Last modified: 08 February 2026