public class ValueHolder{以上代码存在问题是多线程环境下对listeners的竞争访问。既然如此,那在addListener和setValue方法前添加synchronzied。好了些,不过有死锁的可能,这主要是因为你不知道别人在valueChanged方法中会做什么,在调用这个方法时,你手中已经紧紧握住一把锁了。继续改进:
private List listeners = new LinkedList();
private int value;
public interface Listener{
public void valueChanged(int newValue);
}
public void addListener(Listener listener){
listeners.add(listener);
}
public void setValue(int newValue){
value = newValue;
Iterator i = copyOfListeners.iterator();
while(i.hasNext()){
((Listener)i.next()).valueChanged(newValue);
}
}
}
public class ValueHolder{此种实现跟JDK源码util包中Observable实现类似,把竞争访问和死锁都排除了。不过此种实现仍存在问题。比如线程A和线程B依次调用setValue,然后线程B抢在线程A之前通知大家。这样就搞得大家认为ValueHolder中最终value值是线程A设置的值,而实际上是线程B设置的值。没办法,只能继续改进。
private List listeners = new LinkedList();
private int value;
public interface Listener{
public void valueChanged(int newValue);
}
public synchronized void addListener(Listener listener){
listeners.add(listener);
}
public void setValue(int newValue){
List copyOfListeners;
synchronized(this){
value = newValue;
copyOfListeners = new LinkedList(listeners);
}
Iterator i = copyOfListeners.iterator();
while(i.hasNext()){
((Listener)i.next()).valueChanged(newValue);
}
}
}
public class ValueHolder{以上是我提供的一个实现,不知还有没有问题。关键一点,保证setValue按序执行。
private List listeners = new LinkedList();
private int value;
private int seqnum = 0;
private int globalNum = 1;
public interface Listener{
public void valueChanged(int newValue);
}
public synchronized void addListener(Listener listener){
listeners.add(listener);
}
public void setValue(int newValue){
List copyOfListeners;
int localSeqnum;
synchronized(this){
value = newValue;
copyOfListeners = new LinkedList(listeners);
seqnum++;
localSeqnum = seqnum;
}
while(localSeqnum != globalNum){
//Only to wait
}
Iterator i = copyOfListeners.iterator();
while(i.hasNext()){
((Listener)i.next()).valueChanged(newValue);
}
globalNum++;
}
}
注意:在Java中,局部变量都是线程私有的,不用担心访问冲突,要担心的就是实例变量和类变量。