如何在不返回java中使用的示例或数据副本的情况下访问属性?

oogrdqng  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(224)

我正在编写一个多线程程序,我需要访问一个Map,但是我不知道如何确保多个线程不修改Map。我想知道是否有一种方法可以创建一个同步的方法,并在类中返回Map,当程序对其进行更改时,它会反映在primary属性中。
下面是给我一个concurrentmodificationexception的代码。这是因为两个线程同时访问Map吗?删除方法中出现错误。我还包括了notify方法,因为该方法每隔几分钟就被调用一次,我想知道这个错误是否与调用该方法有关。

***我的notifyobserver方法仍然缺少一些逻辑,因此更改的属性总是true。

private static final Map<WeatherDotComLocation, List<Observer>> locationAndObserver = new ConcurrentHashMap<>();

public void remove(Observer o) {
    killThread(o);
    Set<WeatherDotComLocation> weatherLocations = locationAndObserver.keySet();
    for(WeatherDotComLocation location : weatherLocations) {
        List<Observer> observerListToCheck = locationAndObserver.get(location);
        for(Observer suspectObserver : observerListToCheck) {
            if(suspectObserver.equals(o)) {
                observerListToCheck.remove(o);
            }
        }
        if(observerListToCheck.size() == 0) {
            locationAndObserver.remove(location);
        }
    }
}

public void notifyObservers() {
    Set<WeatherDotComLocation> keySet = locationAndObserver.keySet();
    for (WeatherDotComLocation location : keySet) {
        Thread thread = new Thread(() -> {
            WeatherManager weatherManager = new WeatherManager();
            boolean changed = true;
            if(changed) {
                List<WeatherDotComForecast> weatherForecast = weatherManager.pullData(location, 5);
                for(Observer observer : locationAndObserver.get(location)) {
                    observer.update(weatherForecast);
                }
            }
        });
        thread.start();
    }
}
xkftehaa

xkftehaa1#

这样,您只有一个对象示例,线程可以通过 Object object = AClass.getInstance(); :

public class AClass
{
    private static Object instance;

    public static synchronized Object getInstance() {
        if (instance == null)
            instance = new Object();
        return instance;
    }
}
``` `AClass` 还可以定义修改对象状态的其他方法。
yks3o0rb

yks3o0rb2#

synchronized 仅保护同步器内部的块。如果将集合返回到未受保护的区域,则在块外读/写时可以更改此Map。
我认为最简单的选择是使用线程安全的集合,例如

private final Map<String, MyType> map = Collections.synchronizedMap(new HashMap<>());

private final Map<String, MyType> map = new ConcurrentHashMap<>();

它们可以以线程安全的方式使用,而无需使用 synchronized

相关问题