Thread-safe Observer in Java
Fast recall
Quick revision
Core answer
CopyOnWriteArrayList gives snapshot iteration and is useful when notifications greatly outnumber registrations; a locked snapshot or immutable subscription registry may be better when writes are frequent. Do not hold internal locks while calling unknown observer code, and define ordering, re-entrancy, exception, and visibility rules.Interview-ready guide
Interview answer
A thread-safe Observer design needs an explicit concurrency contract: which state snapshot is sent, what a concurrent add or remove means, and how one listener failure affects the rest.
For example, CopyOnWriteArrayList works well for a small configuration-listener registry that is notified often but changed rarely, because iteration sees a stable snapshot; it is not a universal answer because every write copies the array. Another option is to copy a guarded list under a lock and invoke the snapshot after releasing that lock.
Unknown listener code should not run while the subject's internal lock is held because it may block, throw, or re-enter. Subject state may use an atomic immutable snapshot or a lock depending on how many fields must stay consistent.
Thread-safe Observer in Java
Direct Answer
There is no single thread-safe Observer implementation. Protect both the observer collection and the subject state according to their access pattern. CopyOnWriteArrayList gives snapshot iteration and is useful when notifications greatly outnumber registrations; a locked snapshot or immutable subscription registry may be better when writes are frequent. Do not hold internal locks while calling unknown observer code, and define ordering, re-entrancy, exception, and visibility rules.
Common Mistakes & Pitfalls
- Synchronizing everything, including the notify loop — frequent notifications then serialize and throughput collapses.
- Sticking with
ArrayListand assuming rare registration means no concurrency issue — a scheduled job plus an HTTP request will hit the exception. - Parallelizing notification carelessly with
parallelStream()when observers share state — you trade one race for another. - Holding a lock during observer callbacks — if an observer calls back into the subject, you can deadlock.
Check your understanding
Answer these without looking back at the article.
- What is the difference between CopyOnWriteArrayList and Collections.synchronizedList?
- How would Spring's ApplicationEventPublisher handle thread safety compared to a manual Observer?
- How would you notify observers in parallel safely?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.