Multithreading in Java
Multithreading is a concurrent execution mechanism in Java that allows multiple threads to run concurrently within a single program. A thread is a small process that runs alongside the main program. Multithreading allows multiple tasks to be done at the same time, making the program work faster.
Creating and Managing Threads in Java:
1. Extending the Thread
Class:
- Create a class that extends the
Thread
class. - Override the
run
method to define the code that will be executed in the new thread.
class MyThread extends Thread {
public void run() {
// Code to be executed in the new thread
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value " + i);
}
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start(); // Start the first thread
thread2.start(); // Start the second thread
}
}
2. Implementing the Runnable
Interface:
- Create a class that implements the
Runnable
interface. - Implement the
run
method in the class.
class MyRunnable implements Runnable {
public void run() {
// Code to be executed in the new thread
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value " + i);
}
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
thread1.start(); // Start the first thread
thread2.start(); // Start the second thread
}
}
Thread Lifecycle:
- New: The thread is in the new state before the
start
method is called. - Runnable: The thread moves to the runnable state after the
start
method is invoked, and the thread scheduler selects it to be the next to execute. - Blocked: A thread transitions to the blocked state when it wants to access an object that another thread has locked.
- Waiting: A thread transitions to the waiting state when it is waiting for another thread to perform a particular action.
- Timed Waiting: A thread is in the timed waiting state when it calls a method with a specified waiting time.
- Terminated: A thread enters the terminated state when its
run
method completes.
Thread Synchronization:
When multiple threads are accessing shared resources, synchronization is necessary to avoid conflicts and ensure data consistency. This is typically achieved using the synchronized
keyword or using higher-level concurrency utilities provided by the java.util.concurrent
package.
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class SynchronizationExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
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("Count: " + counter.getCount()); // Should be 20000 with proper synchronization
}
}
In this example, the increment and getCount methods are synchronized to prevent data corruption and ensure that only one thread can access them at a time. The join
method is used to wait for threads to complete their execution before printing the final count.