Backend Development 10 min read

Implementing Java Event Notification with the Observer Pattern: Common Pitfalls and Thread‑Safe Solutions

This article explains how to build a Java event‑notification system using the observer pattern, highlights typical mistakes such as concurrent modification and deadlocks, and presents several thread‑safe implementations ranging from synchronized blocks to CopyOnWriteArraySet and atomic primitives.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Implementing Java Event Notification with the Observer Pattern: Common Pitfalls and Thread‑Safe Solutions

Implementing Java event notification via the observer pattern looks easy, but many developers fall into subtle traps; this article walks through the basic setup, common errors, and robust solutions.

We start with a simple StateHolder bean that stores an int state and provides standard getters and setters:

public class StateHolder {
    private int state;
    public int getState() { return state; }
    public void setState(int state) { this.state = state; }
}

Next we define a minimal event class and a listener interface:

public class StateEvent {
    public final int oldState;
    public final int newState;
    StateEvent(int oldState, int newState) {
        this.oldState = oldState;
        this.newState = newState;
    }
}

public interface StateListener {
    void stateChanged(StateEvent event);
}

The StateHolder now holds a Set<StateListener> and methods to add or remove listeners:

private final Set<StateListener> listeners = new HashSet<>();
public void addStateListener(StateListener l) { listeners.add(l); }
public void removeStateListener(StateListener l) { listeners.remove(l); }

Broadcasting directly over the live set can cause ConcurrentModificationException if a listener removes itself during notification. Taking a snapshot of the listener set before iterating avoids this:

private void broadcast(StateEvent e) {
    Set<StateListener> snapshot = new HashSet<>(listeners);
    for (StateListener l : snapshot) {
        l.stateChanged(e);
    }
}

When the holder is used in a multithreaded environment, simple synchronization of every public method (using the intrinsic lock) makes the class thread‑safe but can introduce deadlocks if a listener accesses the holder while the broadcast holds the lock.

To prevent deadlocks we limit synchronization to the listener collection only and perform the actual notification outside the synchronized block:

public void setState(int state) {
    int oldState = this.state;
    synchronized(listeners) { this.state = state; }
    if (oldState != state) {
        broadcast(new StateEvent(oldState, state));
    }
}

A more modern solution replaces the manual snapshot with CopyOnWriteArraySet and stores the state in an AtomicInteger , eliminating the need for explicit locks:

private final Set<StateListener> listeners = new CopyOnWriteArraySet<>();
private final AtomicInteger state = new AtomicInteger();

public void addStateListener(StateListener l) { listeners.add(l); }
public void removeStateListener(StateListener l) { listeners.remove(l); }
public int getState() { return state.get(); }
public void setState(int s) {
    int old = state.getAndSet(s);
    if (old != s) {
        broadcast(new StateEvent(old, s));
    }
}

private void broadcast(StateEvent e) {
    listeners.forEach(l -> l.stateChanged(e));
}

Even with a thread‑safe collection, a faulty listener may throw a RuntimeException and disrupt the notification chain. Wrapping each call in a try‑catch block isolates such failures:

private void broadcast(StateEvent e) {
    listeners.forEach(l -> {
        try { l.stateChanged(e); }
        catch (RuntimeException ex) { /* handle or log */ }
    });
}

In summary, a reliable Java event‑notification system must iterate over a snapshot of listeners, keep synchronization blocks minimal, and protect each listener invocation from unexpected exceptions, with modern concurrent collections offering a concise and safe implementation.

JavaconcurrencySynchronizationThread Safetyobserver patternevent notification
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.