A thread is a lightweight unit of execution that allows a Java program to perform multiple tasks concurrently. Java provides built-in support for multithreading, enabling efficient use of CPU resources and improved application performance.
- Threads share the same memory and resources of a process.
- The main thread starts automatically when a Java program begins execution.
- New threads can be created to execute tasks independently and concurrently.
Creating Threads in Java
There are multiple ways to create threads in Java:
Thread Class
The Thread class is used to create and manage threads in Java. By extending this class and overriding the run() method, a new thread can execute a task independently.
- Extends the Object class and implements the Runnable interface.
- start() creates a new thread and invokes the run() method.
- Suitable for simple thread creation tasks.
The start() method starts a new thread and moves it from the New state to the Runnable state. When scheduled by the JVM, it automatically executes the run() method.
Syntax:
class MyThread extends Thread {
public void run() {
// task to perform
}}
MyThread t = new MyThread();
t.start();
Implementation:
// Extending Thread in Class
import java.io.*;
// Class inheriting Thread class
class MyThread extends Thread
{
// Overriding the run method
@Override
public void run(){
System.out.print("Welcome to GeeksforGeeks.");
}
}
class Geeks
{
public static void main(String[] args)
{
// Creating thread
MyThread t1 = new MyThread();
// Starting thread
t1.start();
}
}
Output
Welcome to GeeksforGeeks.
Runnable Interface
The Runnable interface is used to define a task that can be executed by a thread. It contains a single method, run(), which holds the code to be executed.
- Contains only one method: run().
- Separates task logic from thread creation.
- Supports multiple inheritance since it is an interface.
Note: A class implements Runnable and the task runs when a thread executes its run() method.
Syntax:
class MyTask implements Runnable {
public void run() {
// task to perform
}
}Thread t = new Thread(new MyTask());
t.start();
Implementation:
// Implementing Runnable Interface
import java.io.*;
// Class inheriting Runnable interface
class RunnableClass implements Runnable
{
// Override run method
@Override
public void run()
{
System.out.println("Inside run method");
}
}
class Geeks
{
public static void main(String args[])
{
// Create an object of Runnable target
RunnableClass gfg = new RunnableClass();
// Pass the runnable reference to Thread
Thread t = new Thread( gfg , "gfg");
// Start the thread
t.start();
// Get the name of the thread
System.out.println(t.getName());
System.out.println(t.currentThread().getName());
}
}
Output
gfg main Inside run method
Using Lambda Expressions
Lambda expressions provide a concise way to create and run threads, especially when the task is small and simple.
- Reduces boilerplate code.
- Best for short and simple tasks.
- Works with the Runnable interface.
Note: Lambda expressions allow defining the thread task directly without creating a separate class.
Syntax:
Thread t = new Thread(() -> {
// task to perform
});
t.start();
Implementation:
// Using Lambda Method to Create Thread
import java.io.*;
class Geeks
{
public static void main (String[] args)
{
// Lambda Thread Created
Thread thread1 = new Thread(() -> {
// Operations Performed for thread1
System.out.println("Lambda Thread running");
});
// Running the Thread
thread1.start();
}
}
Output
Lambda Thread running
Using ExecutorService (for Managing Thread Pools)
ExecutorService is a framework that manages and executes threads through a thread pool. It provides a more efficient and scalable approach to multithreading than creating threads manually.
- Uses a pool of reusable threads.
- Simplifies thread management.
- Suitable for executing multiple tasks concurrently.
Note: ExecutorService manages thread creation and execution automatically, improving performance and resource usage.
Syntax:
import java.util.concurrent.*;
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(() -> {
// task to perform
});
executor.shutdown();
Implementation:
// Using ExecutorService
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Geeks
{
public static void main(String[] args)
{
// Create a thread pool with 2 threads
ExecutorService threads = Executors.newFixedThreadPool(2);
// Submitting Threads as Runnable
threads.submit(() -> {
System.out.println("Task 1 is running in " + Thread.currentThread().getName());
});
threads.submit(() -> {
System.out.println("Task 2 is running in " + Thread.currentThread().getName());
});
// Shutdown the threads/executor
threads.shutdown();
}
}
Output
Task 1 is running in pool-1-thread-1 Task 2 is running in pool-1-thread-2