Multithreading
Section 6: Multithreading
Lesson 1: Introduction to Multithreading
1.1 Creating and Running Threads
Multithreading allows the execution of multiple threads concurrently, enabling better utilization of system resources. In Java, you can create threads by extending the Thread class or implementing the Runnable interface.
Example (Extending Thread Class):
class MyThread extends Thread {
public void run() {
// Code to be executed in the thread
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getId() + " - Value " + i);
}
}
}
public class ThreadExample {
public static void main(String[] args) {
// Creating and starting threads
MyThread thread1 = new MyThread();
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
}
}
Example (Implementing Runnable Interface):
class MyRunnable implements Runnable {
public void run() {
// Code to be executed in the thread
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getId() + " - Value " + i);
}
}
}
public class RunnableExample {
public static void main(String[] args) {
// Creating threads using the Runnable interface
Thread thread1 = new Thread(new MyRunnable());
Thread thread2 = new Thread(new MyRunnable());
thread1.start();
thread2.start();
}
}
1.2 Synchronization and Thread Safety
Multithreading can introduce data inconsistency issues when multiple threads access shared resources simultaneously. Synchronization is used to ensure that only one thread can access a shared resource at a time.
Example (Synchronization):
class Counter {
private int count = 0;
// Synchronized method
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizationExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Creating threads that increment the counter
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
// Waiting for threads to finish
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Displaying the final count
System.out.println("Count: " + counter.getCount());
}
}
Lesson 2: Concurrency Utilities
2.1 Java Executor Framework
The Java Executor framework provides a higher-level replacement for managing and controlling threads. It includes interfaces such as Executor, ExecutorService, and ScheduledExecutorService.
Example (Executor Framework):
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorFrameworkExample {
public static void main(String[] args) {
// Creating a fixed-size thread pool
ExecutorService executor = Executors.newFixedThreadPool(2);
// Submitting tasks to the executor
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
System.out.println("Thread ID: " + Thread.currentThread().getId());
});
}
// Shutting down the executor
executor.shutdown();
}
}
2.2 Concurrent Collections
Concurrent collections provide thread-safe implementations of standard Java collections. These collections can be used in multithreaded environments without the need for explicit synchronization.
Example (ConcurrentHashMap):
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
// Creating a concurrent hash map
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// Putting key-value pairs
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
// Iterating through the map
map.forEach((key, value) -> {
System.out.println("Key: " + key + ", Value: " + value);
});
}
}
Multithreading is a powerful concept that can significantly enhance the performance of Java applications. Understanding how to create threads, handle synchronization, and leverage concurrency utilities is essential for developing efficient and scalable software. Practice these examples to solidify your understanding of multithreading in Java.