Мое приложение работает на tomcat с фреймворком Spring и Hibernate. Он использует EHCache в качестве поставщика кэша на уровне обслуживания. Это означает, что объекты, созданные классами обслуживания, помещаются в кэш. (Не вводить в спящий режим объекты Дао).
В этих кэшированных объектах есть несколько объектов коллекции (HashSet, ArrayList, HashMap). Ни одна из них не является синхронизированной коллекцией. Все они не являются потокобезопасными, но они не изменяются приложением после помещения в кеш.
Я находил бесконечный цикл во многих случаях, когда просматривал эту коллекцию. Некоторые из циклов являются циклами итераторов, а некоторые другие — старыми циклами for, которые запускаются на основе индекса int.
Мне удалось преодолеть один бесконечный цикл, заменив HashSet на Collections.synchronizedSet(new 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;
}