Multithreading
Run code in parallel without breaking it: threads, locks, executors, virtual threads.
Take this course in the learning hubLessons
- Threads and RunnableStart real threads with Runnable, and see why start() and run() are not the same thing.
- Lifecycle and interruptionRead a thread’s state and stop one the only way Java supports: by asking it politely.
- Race conditions and synchronizedWatch an update get lost between two threads, then fix it with the simplest tool Java has.
- volatile and visibilityLearn why a plain boolean flag can loop forever, and exactly what volatile does and does not fix.
- Atomic classesDo lock-free counters and updates with AtomicInteger, LongAdder and compare-and-set.
- ReentrantLock and ReadWriteLockUse explicit locks when synchronized is too blunt: timeouts, giving up, and concurrent readers.
- wait/notify and ConditionMake one thread wait for another to change state, without burning CPU in a spin loop.
- Deadlock and how to avoid itUnderstand the cycle behind every deadlock, and the one habit that makes it impossible.
- ExecutorService and thread poolsStop creating threads by hand: submit tasks to a pool and shut it down properly.
- Callable and FutureGet results and exceptions back out of background work using Callable and Future.
- Composing CompletableFutureChain and combine async steps without blocking, and recover cleanly when one of them fails.
- BlockingQueue producer-consumerWire producers to consumers with a bounded queue that does all the waiting for you.
- CountDownLatch and SemaphoreWait for a batch of work to finish, and cap how many threads may enter a section at once.
- ThreadLocalGive each thread a private copy of a value, and learn why cleanup is not optional.
- Virtual threads (Java 21)Run hundreds of thousands of blocking tasks on a few OS threads, using plain blocking code.
- The Java Memory ModelLearn the single rule that makes every other concurrency tool in Java trustworthy.
- synchronized in detailKnow exactly which object a synchronized block locks, and which objects you must never lock on.
- Thread-safe collectionsChoose between ConcurrentHashMap, CopyOnWriteArrayList and a synchronized wrapper, and know their limits.
- Immutability as a concurrency strategyThe cheapest concurrency fix there is: build values that cannot change, so no thread can break them.
- Sizing a thread poolPick core size, max size, queue and rejection policy on purpose instead of copying a default.
- Scheduled and periodic tasksRun work later or on a repeat with ScheduledExecutorService, and pick the repeat mode you actually want.
- ForkJoin and work stealingSplit a big CPU task into halves that idle workers can steal, then join the answers back together.
- Parallel streams and the common poolWhen .parallel() genuinely helps, which pool it borrows, and the traps that make it slower.
- Interruption and cancellationStop work in flight the only way Java allows: set a flag, and write tasks that watch for it.
- Livelock and starvationTwo hangs that are not deadlock: threads that retry forever, and threads that never get a turn.
- Producer-consumer, end to endWire several producers and consumers through one bounded queue, then shut the whole thing down cleanly.
- CompletableFuture error handlingRecover, observe or transform a failure inside an async chain, and get timeouts under control.
- Testing concurrent codeMake races show up on purpose: start threads together, repeat the run, assert on the invariant.
- Structured concurrency (preview)Treat concurrent subtasks like a block of code: they start together, fail together and end together.
- Concurrency vs parallelismTwo different ideas: making progress on many tasks, and truly running them in the same instant.
- Daemon threads and thread factoriesDecide which threads keep the JVM alive, name them properly, and catch what escapes them.
- CyclicBarrier, Phaser and ExchangerSynchronizers that reset: hold every worker at the end of a round, then release them together.
- Safe publication and lazy initHow a reference becomes visible before the object it points to is finished, and the safe fixes.
- StampedLock and optimistic readsRead shared state with no lock at all, then check whether a writer got in while you read.
- False sharing and cache linesTwo threads, two separate counters, and still they fight - over one 64-byte cache line.
- When more threads stop helpingThe serial part caps your speed-up, and small tasks lose more to overhead than they gain.
- Diagnosing a hung applicationTake a thread dump and read it: deadlock, livelock, contention and a full pool all look different.
- Choosing the right concurrency toolA short decision path from the task you have to the executor, lock or queue that fits it.