Multithreading
Multithreading in Java allows you to execute multiple threads (smaller units of a process) concurrently, which can help improve the performance and responsiveness of your Java applications. Java provides built-in support for multithreading through the java.lang.Thread
class and the java.lang.Runnable
interface. Here are the basic concepts and steps involved in working with multithreading in Java:
Creating Threads:
You can create a thread by extending the Thread
class or implementing the Runnable
interface. Implementing Runnable
is often preferred because it allows you to separate the task (runnable object) from the threading mechanism.
Example of extending Thread
:
class MyThread extends Thread {
public void run() {
// Code to be executed in this thread
}
}
Example of implementing Runnable
:
class MyRunnable implements Runnable {
public void run() {
// Code to be executed in this thread
}
}
Creating Thread Objects:
To start a thread, you need to create a Thread
object and pass an instance of your class that extends Thread
or implements Runnable
to its constructor.
MyThread myThread = new MyThread();
Thread thread = new Thread(new MyRunnable());
Starting Threads:
To start a thread, call the start()
method on the Thread
object. This method internally calls the run()
method defined in your class.
myThread.start();
thread.start();
Thread Synchronization:
When multiple threads access shared resources, you may encounter race conditions. Java provides synchronization mechanisms like synchronized
blocks/methods and the java.util.concurrent
package to manage thread synchronization and avoid data corruption.
synchronized void synchronizedMethod() {
// Synchronized code block
}
Thread States:
Threads can be in various states like NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, and TERMINATED. Understanding these states can help in debugging and managing threads effectively.

Thread Sleep
The sleep()
method pauses the execution of a thread for a specified amount of time.
javaCopy codeThread thread = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread: " + i);
try {
Thread.sleep(1000); // Sleep for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
Thread Joining:
You can use the join()
method to wait for a thread to finish its execution before continuing with the current thread.
Thread thread1 = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread 1: " + i);
}
});
Thread thread2 = new Thread(() -> {
for (int i = 1; i <= 5; i++) {
System.out.println("Thread 2: " + i);
}
});
thread1.start();
thread2.start();
try {
thread1.join(); // Wait for thread1 to finish
thread2.join(); // Wait for thread2 to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread is done.");
Thread Priorities:
Threads can have different priorities (1-10), and you can set their priority using the setPriority()
method. Higher-priority threads get more CPU time, but it's not always guaranteed, as it depends on the underlying OS.

Daemon Threads:
Threads can be marked as daemon threads, which will terminate when all non-daemon threads finish their execution. You can set a thread as a daemon using setDaemon(true)
.
thread.setDaemon(true);
This example demonstrates the some built-in methods of the Thread
class:
javaCopy codepublic class ThreadMethodsExample {
public static void main(String[] args) throws InterruptedException {
// Create a new thread
Thread thread = new Thread(() -> {
System.out.println("Thread started.");
try {
// Sleep for 2 seconds
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("Thread interrupted while sleeping.");
return; // Exit the thread
}
System.out.println("Thread resumed after sleep.");
// Check if the thread is interrupted
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread is interrupted.");
} else {
System.out.println("Thread is not interrupted.");
}
});
// Start the thread
thread.start();
// Wait for the thread to finish
thread.join();
// Check if the thread is alive
if (thread.isAlive()) {
System.out.println("Thread is still alive.");
} else {
System.out.println("Thread has finished.");
}
// Interrupt the thread
thread.interrupt();
// Check if the thread is interrupted
if (thread.isInterrupted()) {
System.out.println("Thread is interrupted after interruption.");
} else {
System.out.println("Thread is not interrupted after interruption.");
}
}
}
start()
: Starts the execution of the thread.join()
: Waits for the thread to finish executing.getName()
: Returns the name of the thread.getPriority()
: Returns the priority of the thread.getState()
: Returns the state of the thread.sleep()
: Causes the thread to sleep for a specified number of milliseconds.yield()
: Causes the thread to voluntarily give up the CPU to other threads.interrupt()
: Interrupts the thread.isInterrupted()
: Checks if the thread has been interrupted.isAlive()
: Checks if the thread is still alive.
These methods can be used to control the behavior of threads in your Java applications.
Multithreading in Java can significantly enhance the performance and responsiveness of your applications, but it also introduces challenges related to synchronization and coordination between threads. Careful design and proper synchronization are essential for writing robust multithreaded code.
Last updated
Was this helpful?