使单例观察者模式同步



当我有一个像上面这样的常见单例模式时:为了使其线程保存,我在侦听器列表上同步访问了添加和删除侦听器。但是,对每个侦听器的每次访问都这样做重要吗?例如,应该对setPosition方法进行同样的思考吗?

public class Singleton {
    private static Singleton instance;
    private final List<ChangeListener> listeners = new ArrayList<>();
    private int position;
    private Singleton() {
    }
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    public int getPosition() {
        return position;
    }
    public void setPosition(int position) {
        this.position = position;
        for (ChangeListener l : listeners) {
            l.do(position);
        }
    }
    public void addChangeListener(ChangeListener listener) {
        synchronized (listeners) {
            listeners.add(listener);
        }
    }
    public void removeChangeListener(ChangeListener listener) {
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }
    public interface ChangeListener {
        public void do(int a);
    }
}

我肯定会使setPosition方法同步,因为在中迭代时更改集合不是一个好主意

for (ChangeListener l : listeners) {
    l.do(position);
}

有关更多信息,请查看此处

另一种选择是使用类似java.util.concurrent.CopyOnWriteArrayList的东西。这是线程安全的,但通过每次向列表中写入时获取一个副本来实现这一点。乍一看,这可能看起来很昂贵,但通常情况下,您会不频繁地添加/删除侦听器,并在列表上迭代以更频繁地调用侦听器。当以这种方式使用时,它通常比使用显式同步更有效。

最新更新