【发布时间】:2011-11-13 20:29:27
【问题描述】:
我的应用程序在带有 Spring 和 Hibernate 框架的 tomcat 上运行。它使用 EHCache 作为服务级别的缓存提供者。这意味着由服务类创建的对象被放入缓存中。 (不是休眠的 Dao 对象)。
这些缓存对象中有一些集合对象(HashSet、ArrayList、HashMap)。它们都不是同步集合。都不是线程安全的,但是放入缓存后不会被应用修改。
当我循环浏览这个集合时,我在很多场合都发现了无限循环。其中一些循环是迭代器循环,而另一些则是旧的基于 int 索引运行的 for 循环。
我设法通过用 Collections.synchronizedSet(new HashSet()) 替换 HashSet 来克服一个无限循环。但我不明白使用普通 HashSet 的真正问题,因为它从未被应用程序修改过。 (EHCache 会修改它们吗?)
如果这里使用非线程安全集合有任何问题,请向我解释。
public class HotelDetails implements Serializable { /*Objects in the cache */
private static final long serialVersionUID = 1L;
.....
private Set<String> facilities = new HashSet<String>();
}
以下循环无限运行并炸毁堆
if (hotelDetails.getFacilities() != null && hotelDetails.getFacilities().size() > 0) {
for (String fac : hotelDetails.getFacilities()) {
TFacility f = of.createTFacility();
f.setCode(fac);
f.setValue(fac);
facilities.getFacility().add(f);
}
}
更换HashSet,问题解决
public class HotelDetails implements Serializable { /*Objects in the cache */
private static final long serialVersionUID = 1L;
.....
private Set<String> facilities = Collections.synchronizedSet(new HashSet<String>());
}
这是另一个
private int getRatesStartIndex(GsRoomRate gsRoomRate, List<GsRate> gsRates, Date travelStart) {
Integer startIndex = gsRoomRate.getGsRateIndexes().get(travelStart);
if (startIndex==null) {
for (startIndex=0; startIndex<gsRates.size(); startIndex++) {
GsRate gsRate = gsRates.get(startIndex);
if (travelStart.between(gsRate.getStartDate(), gsRate.getEndDate())) {
gsRoomRate.getGsRateIndexes().put(travelStart, startIndex);
break;
}
}
if (startIndex>=gsRates.size()) startIndex = 0;
}
return startIndex;
}
public class GsRoomRate implements Serializable { /*Objects in the cache */
private static final long serialVersionUID = 1L;
private List<GsRate> gsRates = new ArrayList<GsRate>();
private Map<Date, Integer> gsRateIndexes = new HashMap<Date, Integer>();
}
public class GsRate implements Serializable { /*Objects in the cache */
private static final long serialVersionUID = 1L;
private RBADate startDate;
private RBADate endDate;
}
【问题讨论】:
-
更改为同步集后,您的电话是否会返回?你怎么知道你进入了一个无限循环?您似乎表明您认为您处于无限循环中,因为您的堆空间不足...?
标签: java multithreading collections ehcache hashset