我正在编写一个多线程程序,我需要访问 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/