java - 在 Java 中,如何在不返回实例或数据副本的情况下访问属性?

标签 java multithreading

我正在编写一个多线程程序,我需要访问 Map,但我不知道如何确保多个线程不会修改 Map。我想知道是否有一种方法可以创建一个同步的方法,并返回类中的 Map,当程序对其进行更改时,它会反射(reflect)在主要属性中。

下面是给我一个 ConcurrentModificationException 的代码。这是因为有两个线程 同时访问 map ?错误发生在删除方法中。我还包含了通知方法,因为该方法每隔几分钟就会被调用一次,我想知道这个错误是否与调用该方法有关。

***我的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();
    }
}

最佳答案

synchronized 仅保护synchronized 内的 block 。如果将集合返回到未 protected 区域,则在 block 外读/写时可以更改此映射。

我怀疑最简单的选择是使用线程安全集合,例如

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

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

这些可以以线程安全的方式使用,而不需要使用synchronized

关于java - 在 Java 中,如何在不返回实例或数据副本的情况下访问属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27959506/

相关文章:

java - 在 Java 中引用来自匿名类的变量

java - 如何在JSP中声明int变量?

c++ - 多线程性能

c++ - 在 C++ 中实现 C++ 线程库

multithreading - 如何将对堆栈变量的引用传递给线程?

c - 如何并行化 Windows 消息循环和 Hook 回调逻辑及其创建的 Ruby 线程?

java - Eclipse E4 - 菜单贡献和 PersistedState

java - 如何用java编写JavaScript解析器

java - Thymeleaf CSS 未加载

java - 条件延迟处理