Java Multithreading — Quick Cheat Sheet
Core concepts
Thread vs Runnable: Thread is a class, Runnable is a functional interface. Prefer
Runnable/Callable for separation of concerns.
ExecutorService: manage thread pools; prefer [Link](...) for
reusable threads.
synchronized: intrinsic lock to guard critical sections.
volatile: makes reads/writes to a variable visible to all threads (no atomicity).
Race condition: multiple threads modify shared state without proper synchronization.
Deadlock: two or more threads are waiting forever on locks held by each other.
Small snippets
Create thread using Runnable:
Runnable task = () -> [Link]("Running in thread: " +
[Link]().getName());
Thread t = new Thread(task);
[Link]();
Using ExecutorService:
ExecutorService exec = [Link](4);
[Link](() -> { /* work */ });
[Link]();
Synchronized method:
public synchronized void increment(){ count++; }
Lock example with ReentrantLock:
Lock lock = new ReentrantLock();
[Link]();
try {
// critical section
} finally {
[Link]();
}
Best practices
Prefer higher-level constructs (ExecutorService, Concurrent collections) over manual
thread management.
Keep critical sections short.
Use immutable objects where possible to avoid synchronization.
Use CompletableFuture for async composition.
Common interview tasks to practice
Implement producer-consumer with BlockingQueue.
Fix a race condition in a provided code sample.
Explain how volatile differs from synchronized.