Java provides a robust multithreading model that allows concurrent execution of tasks.
Here’s a list of key thread concepts in Java:
1. Basics of Threads
Thread – A lightweight subprocess that runs concurrently within a program.
Process vs. Thread – A process is an independent execution unit, whereas a thread is
a subset of a process.
Creating Threads
o Extending Thread class
o Implementing Runnable interface
o Using Callable and Future
2. Thread Lifecycle
1. New – Created but not started.
2. Runnable – Ready to run, waiting for CPU time.
3. Blocked – Waiting for a resource to be released.
4. Waiting – Waiting indefinitely until notified.
5. Timed Waiting – Waiting for a specified time.
6. Terminated – Finished execution.
3. Thread Methods
start() – Starts a new thread.
run() – Defines the thread’s task.
sleep(ms) – Pauses execution for a given time.
join() – Waits for a thread to finish.
yield() – Hints that the thread scheduler can switch tasks.
interrupt() – Interrupts a sleeping or waiting thread.
isAlive() – Checks if the thread is still running.
4. Thread Synchronization
synchronized keyword – Ensures only one thread accesses a block/method at a time.
Lock interface (ReentrantLock) – More flexible locking mechanism.
wait(), notify(), notifyAll() – Thread communication methods.
volatile keyword – Ensures visibility of shared variables.
5. Thread Concurrency Utilities (java.util.concurrent)
Executor Framework (ExecutorService) – Manages thread pools.
Callable and Future – Handles asynchronous tasks with return values.
CountDownLatch, CyclicBarrier, Semaphore – Synchronization utilities.
Fork/Join Framework – Splits tasks for parallel execution.
6. Thread Safety Techniques
Immutable Objects – Prevents modification by multiple threads.
Atomic Variables (AtomicInteger, AtomicBoolean) – Provides lock-free thread safety.
ThreadLocal – Stores thread-specific data.
7. Deadlocks, Starvation & Livelocks
Deadlock – Two or more threads waiting on each other indefinitely.
Starvation – Low-priority thread never gets CPU time.
Livelock – Threads keep changing states without making progress.
8. Daemon Threads
Background threads that run in the JVM until all user threads finish (e.g., Garbage
Collector thread).
9. Thread Groups
Organizes threads into groups for collective management.
10. Thread Priorities
Threads have priority values (1 to 10) influencing scheduling.
Would you like details on any specific topic? 😊
Thread Synchronization in Java
Thread synchronization is a mechanism that ensures that multiple threads do not interfere
with each other when accessing shared resources. Java provides several ways to handle
synchronization:
1. synchronized Keyword
The synchronized keyword is used to restrict access to a block of code or a method
so that only one thread can execute it at a time.
It prevents race conditions when multiple threads try to modify shared data
simultaneously.
Example: Synchronized Method
java
CopyEdit
class Counter {
private int count = 0;
public synchronized void increment() { // Only one thread can execute
this method at a time
count++;
}
public int getCount() {
return count;
}
}
Example: Synchronized Block
java
CopyEdit
class Counter {
private int count = 0;
public void increment() {
synchronized(this) { // Lock is applied only on this block
count++;
}
}
public int getCount() {
return count;
}
}
A synchronized block is preferred over a synchronized method when we need more
fine-grained control.
2. Lock Interface (ReentrantLock)
ReentrantLock is an implementation of the Lock interface, providing more advanced
synchronization than the synchronized keyword.
It allows:
o Fairness policy (first-come-first-serve thread execution)
o Interruptible locks (a thread can be interrupted while waiting for a lock)
o Try-lock mechanism (check if the lock is available without blocking)
Example of ReentrantLock
java
CopyEdit
import java.util.concurrent.locks.ReentrantLock;
class SharedResource {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock(); // Acquiring the lock
try {
count++;
} finally {
lock.unlock(); // Releasing the lock
}
}
public int getCount() {
return count;
}
}
Why use ReentrantLock over synchronized?
o Provides explicit lock control (lock/unlock manually)
o Supports tryLock() (check if the lock is available without waiting)
o Can be used with Condition variables for fine-grained thread control
3. wait(), notify(), and notifyAll()
These methods are used for thread communication inside synchronized blocks or methods.
wait() → Makes the thread wait until another thread calls notify()
notify() → Wakes up a single thread that is waiting
notifyAll() → Wakes up all waiting threads
Example: Producer-Consumer Problem
java
CopyEdit
class SharedQueue {
private int data;
private boolean available = false;
public synchronized void put(int value) {
while (available) { // Wait if data is already available
try { wait(); } catch (InterruptedException e)
{ e.printStackTrace(); }
}
data = value;
available = true;
notify(); // Notify waiting threads
}
public synchronized int get() {
while (!available) { // Wait if no data is available
try { wait(); } catch (InterruptedException e)
{ e.printStackTrace(); }
}
available = false;
notify(); // Notify waiting threads
return data;
}
}
Why use wait() and notify()?
o Helps in avoiding busy waiting (CPU wastage)
o Enables thread communication efficiently
4. volatile Keyword
Ensures that a shared variable's value is always read from the main memory and
not from a thread’s cache.
This guarantees visibility across multiple threads.
Example without volatile (Incorrect Behavior)
java
CopyEdit
class SharedResource {
private boolean running = true;
public void stop() {
running = false; // Other threads may not see this change
immediately
}
public void start() {
while (running) {
// Some work
}
}
}
The running variable might be cached by a thread, leading to an infinite loop even
after stop() is called.
Example with volatile (Correct Behavior)
java
CopyEdit
class SharedResource {
private volatile boolean running = true; // Ensures visibility across
threads
public void stop() {
running = false; // All threads will immediately see this update
}
public void start() {
while (running) {
// Some work
}
}
}
The volatile keyword ensures immediate visibility of changes made by one thread
to all other threads.
Conclusion
Feature Purpose
synchronized Ensures mutual exclusion (only one thread at a time)
ReentrantLock More flexible locking mechanism
wait(), notify() Thread communication mechanisms
volatile Ensures visibility of shared variables
Each method has its use case:
Use synchronized for simple mutual exclusion.
Use ReentrantLock for complex locking needs.
Use wait()/notify() for thread coordination.
Use volatile for variable visibility (but not atomicity).
Would you like an example for a specific use case? 😊