5

我对java很陌生,如果我说的任何话听起来很新鲜,请提前抱歉,请保持温和。

我已经实现了一个基本的观察者模式。一些观察者应该只听一次更新,然后立即将自己从观察者/听众列表中删除。但是,每当我尝试这样做时,都会遇到著名的java.util.concurrentmodificationexception错误。

我显然收到了这个错误,因为我在更改列表的同时仍在对其进行迭代,但我仍然不确定什么是正确的解决方案。我想知道我是否以正确的方式这样做。如果我是,那么需要什么修复才能使其正常工作?如果我不是,我想获得一些建议,以更好地实现我正在尝试做的事情。

这是我的代码:

public interface Listener {
    public void onValueChange(double newValue);
}   


public class Observed {
    private int value;
    List<Listener>  listeners  = new ArrayList<>();

    public void addListener(Listener toAdd) {
        listeners.add(toAdd);
    }

    public void removeListener(Listener toRemove) {
        listeners.remove(toRemove);
    }

    public void changeValue(double newValue) {
        value = newValue;
        for (Listener l : listeners) l.onValueChange(newValue);                               
    }
}


public class SomeClassA implements Listener{
    private Observed observed;

    SomeClassA(Observed observed) {
        this.observed = observed;
    }

    @Override
    public void onValueChange(double newValue) {
        System.out.println(newValue);
        observed.removeListener(this);
    }
}


public class SomeClassB implements Listener{
   @Override
    public void onValueChange(double newValue) {
        System.out.println(newValue);
    } 
}



public class ObserverTest {
    public static void main(String[] args) {
        Observed observed = new Observed();
        SomeClassA objectA = new SomeClassA(observed);
        SomeClassB objectB = new SomeClassB();

        observed.addListener(objectB);
        observed.addListener(objectA);

        observed.changeValue(4);
    }
}
4

3 回答 3

7

一种方法是使用 CopyOnWriteArraylist而不是 ArrayList 。

CopyOnWriteArraylist 是 ArrayList 的线程安全变体,其中所有可变操作(添加、设置等)都是通过制作底层数组的新副本来实现的。

将其扔进您的案子的原因

您正在直接修改集合,同时它在方法 changeValue() 下迭代集合

于 2013-10-05T12:08:02.793 回答
1

迭代集合时,不能从集合中删除项目。也就是说,除非您使用Iterator#remove方法。由于在这种情况下这是不可能的,因此另一种方法是复制您的侦听器列表并对其进行迭代。在这种情况下,原始侦听器列表可以由各个侦听器自由操作:

public void changeValue(double newValue) {
    value = newValue;
    List<Listener> copyOfListeners = new ArrayList<Listener>(listeners);
    for(Listener l : copyOfListeners) {
        l.onValueChange(newValue);
    }
}
于 2013-10-05T12:28:29.187 回答
0

下面的代码有效,所以你可以尝试它所做的任何事情。

import java.util.Observable;
import java.util.Observer;
class Model extends Observable {
    public void setX(double x) {
        this.x=x;
        System.out.println("setting x to "+x);
        setChanged();
        notifyObservers();
    }
    double x;
}
class A implements Observer {
    A(Model model) {
        this.model=model;
    }
    @Override public void update(Observable arg0,Object arg1) {
        System.out.println(getClass().getName()+" "+((Model)arg0).x);
        ((Model)arg0).deleteObserver(this);
    }
    Model model;
}
class B implements Observer {
    @Override public void update(Observable arg0,Object arg1) {
        System.out.println(getClass().getName()+" "+((Model)arg0).x);
    }
}
public class So19197579 {
    public static void main(String[] arguments) {
        Model model=new Model();
        model.addObserver(new A(model));
        model.addObserver(new B());
        model.setX(4);
        model.setX(8);
    }
}
于 2013-10-05T12:43:04.237 回答