Multithreading and Concurrency in Java – Complete Guide
Learn the concepts of multithreading and concurrency in Java, including thread creation, synchronization, executor framework, and concurrent collections for efficient parallel processing.
Java's multithreading and concurrency capabilities allow programs to execute multiple tasks in parallel, improving performance, scalability, and responsiveness.
1. Thread Basics
- A thread is the smallest unit of execution in a program.
- Java provides multithreading support to allow the execution of multiple threads in parallel.
Key Concepts:
- Each thread has its own program counter, stack, and local variables.
- Threads share global memory, so synchronization is required to manage shared resources.
2. Creating Threads (Thread Class, Runnable Interface)
- Thread Class: You can extend the
Threadclass to create a thread by overriding therun()method. - Runnable Interface: You can implement the
Runnableinterface, which allows the class to be executed by a thread.
Using Thread Class
Using Runnable Interface
Key Points:
Thread.start()is used to initiate a thread.run()contains the task to be executed by the thread.
3. Thread Lifecycle
A thread goes through various stages during its execution:
- New: The thread is created but not started.
- Runnable: The thread is ready for execution and waiting for CPU time.
- Blocked: The thread is waiting to acquire resources or locks.
- Terminated: The thread has completed its execution.
Thread States Diagram:
4. Thread Priority
- Threads in Java have a priority that determines the order in which they are scheduled.
- Priority values range from
Thread.MIN_PRIORITY (1)toThread.MAX_PRIORITY (10).
Example:
Key Points:
- Thread priority is managed using
setPriority(int priority). - Thread priority is not guaranteed; it depends on the underlying OS scheduler.
5. Synchronization
- Synchronization ensures that only one thread can access a resource at a time.
- This is critical when multiple threads share data (e.g., updating a counter or modifying a list).
Example – Synchronized Method:
Key Points:
synchronizedkeyword ensures that only one thread can execute a method at a time.- Synchronization prevents data inconsistency and race conditions.
6. Locks and Monitors
- Java uses monitors to allow only one thread to access a critical section of code.
- ReentrantLock is an alternative to synchronized methods/blocks, providing more flexibility.
Key Points:
- ReentrantLock provides explicit lock control.
- Use
lock.lock()andlock.unlock()for manual locking and unlocking.
7. Deadlock, Livelock, Race Condition
- Deadlock: When two or more threads wait forever for each other to release resources.
- Livelock: Threads are actively trying to make progress, but due to resource contention, they never succeed.
- Race Condition: When the output depends on the timing of thread execution, resulting in inconsistent data.
Example of Deadlock:
Key Points:
- Avoiding deadlock: Ensure a consistent ordering of resource acquisition.
- Use timeouts or tryLock() to handle deadlocks.
8. Executor Framework
- The Executor Framework provides a higher-level replacement for managing threads.
- It decouples task submission from thread management.
Example – Using ExecutorService:
Key Points:
- ExecutorService manages a pool of threads, handling tasks efficiently.
- Use
submit()for task execution andshutdown()to stop the executor.
9. Callable and Future
- Callable: Similar to
Runnable, but it can return a result or throw an exception. - Future: Represents the result of an asynchronous computation.
Example – Using Callable and Future:
Key Points:
- Callable allows returning a result from a thread.
- Future.get() blocks until the result is available.
10. ThreadPoolExecutor
ThreadPoolExecutoris a customizable thread pool that handles a large number of tasks efficiently by reusing threads.
Example:
Key Points:
- ThreadPoolExecutor allows fine-grained control over thread pool configuration.
11. ScheduledExecutorService
ScheduledExecutorServiceallows scheduling tasks with fixed-rate or fixed-delay execution.
Example – Scheduling a Task:
12. Concurrent Collections (ConcurrentHashMap, CopyOnWriteArrayList)
- Java provides thread-safe collections that allow concurrent access without requiring manual synchronization.
Example – ConcurrentHashMap:
Key Points:
- ConcurrentHashMap: Thread-safe without blocking for reading.
- CopyOnWriteArrayList: Allows thread-safe modifications of lists.