我有一个一次可以被很多线程访问的java类,并且要确保它是线程安全的。该类有一个私有字段,它是一个字符串列表的字符串映射。我已经实现了地图作为一个ConcurrentHashMap以确保获得期权和看跌期权是线程安全的:使用列表映射的Java并发性
public class ListStore {
private Map<String, List<String>> innerListStore;
public ListStore() {
innerListStore = new ConcurrentHashMap<String, List<String>>();
}
...
}
所以考虑到获取并把该地图是线程安全的,我关心的是存储在地图列表。例如,考虑下面的方法来检查,如果在给定的列表中存在在店里给定的条目(我省略了错误检查简洁):
public boolean listEntryExists(String listName, String listEntry) {
List<String> listToSearch = innerListStore.get(listName);
for (String entryName : listToSearch) {
if(entryName.equals(listEntry)) {
return true;
}
}
return false;
}
这似乎是我需要的全部内容同步因为如果在此方法迭代它时另一个方法更改了innerListStore.get(listName)处列表的内容,则会引发ConcurrentModificationException。
这是正确的,如果是这样,我在innerListStore同步或将同步本地listToSearch变量工作?
更新:感谢您的答复。这听起来像我可以在列表本身进行同步。欲了解更多信息,这里是add()方法,它可以在listEntryExists()方法是在另一个线程运行的同时运行:
public void add(String listName, String entryName) {
List<String> addTo = innerListStore.get(listName);
if (addTo == null) {
addTo = Collections.synchronizedList(new ArrayList<String>());
List<String> added = innerListStore.putIfAbsent(listName, addTo);
if (added != null) {
addTo = added;
}
}
addTo.add(entryName);
}
如果这是修改存储在基础表的唯一方法在映射中,没有公共方法返回映射或映射中的条目的引用,我可以同步列表本身的迭代,并且add()的实现是否足够?
你的add()实现被破坏了。你需要正确处理'putIfAbsent()'的结果(否则你可能会添加到错误的列表中)。 – jtahlborn 2011-05-31 18:55:22
@jtahlborn你是说我需要在putIfAbsent()返回的List上调用add()吗?如果是这样,我不同意。 putIfAbsent()返回之前与该键关联的**,这将是错误的列表。对? – Cameron 2011-05-31 19:00:37
请重新阅读'putIfAbsent()'方法的文档(注意该方法的名称)。 – jtahlborn 2011-05-31 19:12:32