使单例观察者模式同步?
Make singleton observer pattern synchronized?
当我有一个像上面那样的常见单例模式时:为了节省线程,我在监听器列表上同步添加和删除监听器。
但是对每个听众的每次访问都这样做重要吗?例如,是否应该使用 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);
}
更多信息,请查看here
另一种方法是使用类似 java.util.concurrent.CopyOnWriteArrayList
的方法。这是线程安全的,但通过每次写入列表时复制一份来实现。乍一看,这可能看起来很昂贵,但通常您会 adding/removing 很少听众并且遍历列表以更频繁地调用听众。以这种方式使用时,通常比使用显式同步更有效。
当我有一个像上面那样的常见单例模式时:为了节省线程,我在监听器列表上同步添加和删除监听器。 但是对每个听众的每次访问都这样做重要吗?例如,是否应该使用 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);
}
更多信息,请查看here
另一种方法是使用类似 java.util.concurrent.CopyOnWriteArrayList
的方法。这是线程安全的,但通过每次写入列表时复制一份来实现。乍一看,这可能看起来很昂贵,但通常您会 adding/removing 很少听众并且遍历列表以更频繁地调用听众。以这种方式使用时,通常比使用显式同步更有效。