A structured set of hands-on exercises to practice concurrency in Java.
Organized from easy → advanced with hints and stretch goals.
- Goal: Show how multiple threads updating a shared counter cause incorrect results.
- Hint: Use a normal
intand increment inside multiple threads withoutsynchronized. - Stretch: Fix using
synchronized, thenAtomicInteger.
- Goal: Observe thread lifecycle (
NEW,RUNNABLE,TERMINATED). - Hint: Use
Thread.getState(). - Stretch: Write code that pushes a thread into
WAITINGusingwait()andnotify().
- Goal: Implement counter with
synchronized,ReentrantLock, andAtomicInteger. - Stretch: Compare performance of the three.
- Goal: Implement using
wait()/notify(). - Hint: Shared buffer (list/queue), producer adds, consumer removes.
- Stretch: Replace with
BlockingQueue.
- Goal: Write two threads holding different locks and waiting for each other.
- Stretch: Fix deadlock using lock ordering or
tryLock().
- Goal: Implement mini
ExecutorService:- Task queue
- Worker threads consuming tasks
- Hint: Use
BlockingQueue<Runnable>. - Stretch: Add graceful shutdown logic.
- Goal: Print "Hello" every 2 seconds using
ScheduledExecutorService. - Stretch: Cancel after 10 seconds.
- Goal: Simulate shared cache → multiple readers, fewer writers.
- Hint: Use
ReentrantReadWriteLock. - Stretch: Add cache invalidation with
ScheduledExecutorService.
- Goal: Worker threads start after all are ready.
- Hint: Use
CountDownLatch. - Stretch: Convert to
CyclicBarrier(threads meet at barrier repeatedly).
- Goal: Implement your own
BlockingQueuewithwait()/notify(). - Stretch: Add timeout support for
offer()andpoll().
- Goal: Call three async tasks, combine results.
- Hint: Use
CompletableFuture.supplyAsync(), thenthenCombine(). - Stretch: Handle exceptions with
exceptionally().
- Goal: Sum an array of integers using
RecursiveTask. - Stretch: Compare runtime with sequential loop.
- Goal: Solve using
ReentrantLock. - Stretch: Avoid deadlock using resource hierarchy or
tryLock.
- Goal: Write code that deadlocks → run
jstackto analyze. - Stretch: Fix by ordering locks.
- Goal: Allow max 5 requests per second.
- Hint: Use
Semaphore. - Stretch: Implement token bucket algorithm.
- Start with Level 1–2 → basics and synchronization.
- Move to Level 3–4 → practical tools (
ExecutorService, locks, latches). - Attempt Level 5 → system design & real-world patterns.
- Always code small demos — don’t just read.
Happy coding 🚀