Archief - Java/JPA HashMap voor cache

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

passero

Legacy Member
Ik heb een JSF applicatie die gebruik maakt van JPA als persistentie framework.

Ik heb een bepaald object dat ik constant in memory wil opslaan voor performantie redenen. Dat object wordt elke minuut geupdate via een REST API die aangeroepen wordt door een desktop client van de gebruiker.
In de Web app gebruik ik hetzelfde object om die realtime data te tonen, Die wordt ook automatisch na 1 minuut geupdate.

In mijn eerste versie voerde elke REST API een select + update uit.
Elke request van de realtime data voerde daarbij ook een update uit.
Dit per user!

Nu heb ik mijn code aangepast en een in memory cache geschreven door gebruik te maken van een static HashMap:

Code:
private static HashMap<String,Realtime> rtCache = new HashMap<String,Realtime>();

public Realtime getRealtime(Station station){
		if(rtCache.get(station.getApiKey()) == null){
			TypedQuery<Realtime> query = em.createQuery("select r from Realtime r where r.station",Realtime.class);
			query.setParameter("s", station);
			Realtime rt = query.getSingleResult();
			rtCache.put(station.getApiKey(), rt);
		}
		return rtCache.get(station.getApiKey());
	}

Dit werkt en nu wordt er enkel een update naar de DB gestuurd.
In princiepe heb ik zelf geen DB nodig voor die data en kan ik dit object enkel in memory laten bestaan maar de DB is nodig voor het geval de client geen data heeft verzonden. Dan kan ik toch de laatste data tonen.

Nu vroeg ik me af of dit een goeie techniek is.
HashMap is voor zover ik weet niet synchronized. Is dit een probleem als ik met pakweg 100 gebruikers op de site zit en dus +/- 3 requests/seconde te verwerken krijg.
Het enige probleem dat ik momenteel zie is dat de realtime data op de website soms eens gaan missen door het niet synchronized te zijn maar op zich is dat geen ramp.

ultddave

Legacy Member
Nee inderdaad, de HashMap is niet synchronized. Indien je een gesynchroniseerde wilt, dan moet je de ConcurrentHashMap gebruiken (ConcurrentHashMap (Java 2 Platform SE 5.0))

Belangrijk is wel dit; "Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove)."

Het enige probleem dat ik momenteel zie is dat de realtime data op de website soms eens gaan missen door het niet synchronized te zijn maar op zich is dat geen ramp.
Inderdaad, dus ik denk dat het geen probleem is om zo een HashMap dan te gebruiken ;).

PS; Eventueel eens kijken naar het keyword "volatile", dat kan ook handig zijn in deze situatie ;).

The volatile keyword in Java

Greetz,
Dave

forloRn_

Legacy Member
Synchronized heeft niks te maken met het missen van updates, synchronized heeft met thread-safety te maken, en dat is het voorkomen dat objecten in een ongeldige toestand komen wanneer parallelle threads die toestand wijzigen, in dit geval door gebieden in de code af te bakenen waarin threads serieel moeten lopen.

Volatile zal je hier niet helpen vermits je dan enkel de access tot de reference naar je rtCache thread-safe maakt, en niet het object zelf.

Met een SynchronizedHashMap (of wrappen met een Collections.SynchronizedMap) is je cachethread-safe voor individuele operaties, maar niet voor combinaties daarvan. Het resultaat is dan dat je in sommige gevallen 1) updates zult missen en 2) de query uitvoert wanneer de waarde al in je cache zit.

Ik zou met een synchronized block werken rond je get/put.

passero

Legacy Member
Thanks.
ik heb nog wat gezocht ondertussen en denk dat ik gewoon ehcache ga gebruiken.
Dan ben ik zeker dat het goed gedaan is :)

ultddave

Legacy Member
forloRn_ zei:
Synchronized heeft niks te maken met het missen van updates, synchronized heeft met thread-safety te maken, en dat is het voorkomen dat objecten in een ongeldige toestand komen wanneer parallelle threads die toestand wijzigen, in dit geval door gebieden in de code af te bakenen waarin threads serieel moeten lopen.
Inderdaad, klopt wat je zegt ;).

forloRn_ zei:
Ik zou met een synchronized block werken rond je get/put.
True, achteraf gezien is dat misschien wel beter. Had niet opgemerkt dat hij nog eens een "put" ging doen in die if-test.

Ik zou dan wel die laatste "get" weghalen als die niet echt nodig is;
Code:
		Object key = rtCache.get(station.getApiKey());

		if(key == null){
			TypedQuery<Realtime> query = em.createQuery("select r from Realtime r where r.station",Realtime.class);
			query.setParameter("s", station);
			Realtime rt = query.getSingleResult();
			rtCache.put(station.getApiKey(), rt);
			key = rt;
		}
		return key;

ik heb nog wat gezocht ondertussen en denk dat ik gewoon ehcache ga gebruiken.
Kende ik niet, is wel interessant, straks zelf eens wat meer over opzoeken ;).

passero

Legacy Member
Ik heb ondertussen ehcache geimplementeerd.
Is wel handig.
Je kan er ook dingen aan toevoegen zoals een TTL, max in memory elements, max on disk, size van de cache enzo.
Het is ook goed als ik naar een clustered environment ga want ehcache kan distributed geconfigureerd worden.

Jerre Muesli

Legacy Member
Ehcache is een hele bekende inderdaad. Je kan ook eens Guava van Google bekijken, meer pecifiek naar CacheBuilder.
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan