使单例观察者模式同步?

时间:2015-02-09 10:03:12

标签: java synchronization

当我有一个像上面那样的常见单例模式时:为了使其保存线程,我可以在侦听器列表中同步添加和删除侦听器。 但是每个听众的每次访问都很重要吗?例如,是否应该使用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);
    }
}

2 个答案:

答案 0 :(得分:2)

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

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

有关详细信息,请查看here

答案 1 :(得分:1)

另一种方法是使用java.util.concurrent.CopyOnWriteArrayList之类的东西。这是线程安全的,但每次写入列表时都要复制一份。乍一看,这可能看起来很昂贵但通常你会不经常添加/删除监听器并迭代列表以更频繁地调用监听器。以这种方式使用时,使用显式同步通常更有效。