What is Java Threads?
A thread is a lightweight subprocess, a smallest unit of processing in Java. It allows a program to execute multiple tasks concurrently, making efficient use of CPU resources. Java provides robust support for multithreading through the java.lang.Thread class and the java.util.concurrent package.
What is a Thread?
A thread represents a single sequence of execution within a program. Every Java application has at least one thread — the main thread, which starts the execution of the program. Developers can create additional threads to perform tasks simultaneously.
Advantages of Threads
- Concurrency: Threads enable parallel execution of tasks, improving application performance.
- Efficient CPU Utilization: Threads allow programs to utilize multiple cores of modern CPUs.
- Improved Responsiveness: Threads keep GUI applications responsive while handling background tasks.
- Simpler Program Design: Threads simplify the design of real-time applications.
Creating Threads in Java
Java provides two primary ways to create a thread:
- Extending the Thread Class
- Implementing the Runnable Interface
1. Extending the Thread Class
You can create a custom thread class by extending the Thread class and overriding its run() method.
Example:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // Start the thread
}
}
Output:
Thread is running...
Explanation:
- The start() method begins the execution of the thread, invoking the run() method in a separate thread of execution.
2. Implementing the Runnable
Interface
The preferred approach to creating threads is by implementing the Runnable interface. It promotes better design since Java doesn’t support multiple inheritance.
Example:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running using Runnable...");
}
}
public class ThreadExample {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start(); // Start the thread
}
}
Output:
Thread is running using Runnable...
Thread Lifecycle
A thread in Java goes through the following states during its lifecycle:
- New: Thread is created but not started.
- Runnable: Thread is ready to run but waiting for CPU time.
- Running: Thread is executing.
- Blocked/Waiting: Thread is waiting for resources or another thread.
- Terminated: Thread has completed its execution.
Key Thread Methods
Method | Description |
---|---|
start() | Starts a thread and invokes the run() method. |
run() | Defines the task to be executed by the thread. |
sleep(milliseconds) | Puts the thread to sleep for a specified duration. |
join() | Waits for a thread to finish before proceeding. |
yield() | Temporarily pauses the thread to allow others to execute. |
isAlive() | Checks if the thread is still running. |
Example of Thread Lifecycle Methods:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running...");
try {
Thread.sleep(1000); // Pause for 1 second
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
System.out.println("Thread finished.");
}
}
public class ThreadLifecycle {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start(); // Start the thread
thread.join(); // Wait for thread to finish
System.out.println("Main thread finished.");
}
}
Output:
Thread is running...
Thread finished.
Main thread finished.
Synchronization in Threads
When multiple threads access shared resources, data inconsistency can occur. Java provides synchronization to prevent such issues.
Using the synchronized Keyword
The synchronized keyword ensures that only one thread can access a block of code or method at a time.
Example:
class SharedResource {
synchronized void printNumbers() {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}
}
class MyThread extends Thread {
SharedResource resource;
MyThread(SharedResource resource) {
this.resource = resource;
}
@Override
public void run() {
resource.printNumbers();
}
}
public class SynchronizationExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
MyThread thread1 = new MyThread(resource);
MyThread thread2 = new MyThread(resource);
thread1.start();
thread2.start();
}
}
Output:
Thread-0: 1
Thread-0: 2
Thread-0: 3
Thread-0: 4
Thread-0: 5
Thread-1: 1
Thread-1: 2
Thread-1: 3
Thread-1: 4
Thread-1: 5
Multithreading vs. Multiprocessing
Feature | Multithreading | Multiprocessing |
---|---|---|
Definition | Multiple threads within a single process. | Multiple processes running concurrently. |
Memory Usage | Shares memory space. | Each process has its own memory. |
Overhead | Low overhead. | High overhead. |