Guava Cache

1. Prehľad

V tomto výučbe sa pozrieme na Guava Cache implementácia - základné použitie, zásady vysťahovania, obnovenie medzipamäte a niekoľko zaujímavých hromadných operácií.

Na záver sa pozrieme na používanie oznámení o odstránení, ktoré je cache schopná rozposlať.

2. Ako používať vyrovnávaciu pamäť Guava

Začnime jednoduchým príkladom - uložme do medzipamäte veľké písmená String inštancie.

Najskôr vytvoríme CacheLoader - slúži na výpočet hodnoty uloženej v pamäti cache. Z tohto použijeme užitočné CacheBuilder aby sme vytvorili našu cache pomocou daných špecifikácií:

@Test public void whenCacheMiss_thenValueIsComputed () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (reťazcový kľúč) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder (). build (nakladač); assertEquals (0, cache.size ()); assertEquals ("AHOJ", cache.getUnchecked ("ahoj")); assertEquals (1, cache.size ()); }

Všimnite si, ako pre náš kľúč „ahoj“ v medzipamäti nie je žiadna hodnota - a tak je hodnota vypočítaná a uložená do pamäte cache.

Upozorňujeme tiež, že používame getUnchecked () operation - toto spočíta a načíta hodnotu do cache, ak ešte neexistuje.

3. Pravidlá vysťahovania

Každá vyrovnávacia pamäť musí v určitom okamihu odstrániť hodnoty. Poďme diskutovať o mechanizme vyradenia hodnôt z medzipamäte - pomocou rôznych kritérií.

3.1. Vysťahovanie podľa veľkosti

Môžeme obmedziť veľkosť našej medzipamäte použitím maximumSize (). Ak vyrovnávacia pamäť dosiahne limit, najstaršie položky budú vyradené.

V nasledujúcom kóde obmedzíme veľkosť medzipamäte na 3 záznamy:

@Test public void whenCacheReachMaxSize_thenEviction () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder (). maximumSize (3) .build (nakladač); cache.getUnchecked ("prvý"); cache.getUnchecked ("druhý"); cache.getUnchecked ("tretí"); cache.getUnchecked ("ďalej"); assertEquals (3, cache.size ()); assertNull (cache.getIfPresent ("prvý")); assertEquals ("FORTH", cache.getIfPresent ("ďalej")); }

3.2. Vysťahovanie podľa hmotnosti

Môžeme tiež obmedziť veľkosť vyrovnávacej pamäte pomocou vlastnej funkcie hmotnosti. V nasledujúcom kóde používame dĺžka ako naša vlastná funkcia hmotnosti:

@Test public void whenCacheReachMaxWeight_thenEviction () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (reťazcový kľúč) {návratový kľúč.toUpperCase (); }}; Váhová váha weightByLength; weighByLength = new Weigher () {@Override public int weigh (String key, String value) {return value.length (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder () .maximumWeight (16) .weigher (weighByLength) .build (nakladač); cache.getUnchecked ("prvý"); cache.getUnchecked ("druhý"); cache.getUnchecked ("tretí"); cache.getUnchecked ("posledný"); assertEquals (3, cache.size ()); assertNull (cache.getIfPresent ("prvý")); assertEquals ("POSLEDNÉ", cache.getIfPresent ("posledné")); }

Poznámka: Vyrovnávacia pamäť môže odstrániť viac ako jeden záznam, aby sa vytvoril priestor pre nový veľký záznam.

3.3. Vysťahovanie podľa času

Okrem použitia veľkosti na vysťahovanie starých záznamov môžeme využiť aj čas. V nasledujúcom príklade prispôsobujeme našu vyrovnávaciu pamäť odstrániť záznamy, ktoré boli nečinné 2ms:

@ Test public void whenEntryIdle_thenEviction () hodí InterruptedException {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder () .expireAfterAccess (2, TimeUnit.MILLISECONDS) .build (nakladač); cache.getUnchecked ("ahoj"); assertEquals (1, cache.size ()); cache.getUnchecked ("ahoj"); Závit. Spánok (300); cache.getUnchecked ("test"); assertEquals (1, cache.size ()); assertNull (cache.getIfPresent ("ahoj")); }

Môžeme tiež vysťahovať záznamy na základe ich celkového živého času. V nasledujúcom príklade vyrovnávacia pamäť odstráni záznamy po 2 ms od uloženia:

@Test public void whenEntryLiveTimeExpire_thenEviction () hodí InterruptedException {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder () .expireAfterWrite (2, TimeUnit.MILLISECONDS) .build (nakladač); cache.getUnchecked ("ahoj"); assertEquals (1, cache.size ()); Závit. Spánok (300); cache.getUnchecked ("test"); assertEquals (1, cache.size ()); assertNull (cache.getIfPresent ("ahoj")); }

4. Slabé klávesy

Ďalej sa pozrime, ako dosiahnuť, aby naše kľúče medzipamäte mali slabé referencie - čo umožňuje zberaču odpadu zbierať kľúče medzipamäte, na ktoré sa inde neodkazuje.

V predvolenom nastavení majú kľúče aj hodnoty medzipamäte silné odkazy, ale môžeme nastaviť, aby naša pamäť ukladala kľúče pomocou slabých odkazov pomocou slabé klávesy () ako v nasledujúcom príklade:

@Test public void whenWeakKeyHasNoRef_thenRemoveFromCache () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder (). slabéKeys (). zostavenie (nakladač); }

5. Mäkké hodnoty

Smetiarom môžeme povoliť zhromažďovanie našich hodnôt v pamäti pomocou softValues ​​() ako v nasledujúcom príklade:

@Test public void whenSoftValue_thenRemoveFromCache () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder (). softValues ​​(). build (nakladač); }

Poznámka: Mnoho mäkkých referencií môže mať vplyv na výkon systému - používa sa radšej maximumSize ().

6. Rukoväť nulový Hodnoty

Teraz sa pozrime, ako zaobchádzať s vyrovnávacou pamäťou nulový hodnoty. Predvolene, Guava Cache spôsobí výnimky, ak sa pokúsite načítať a nulový hodnota - pretože nemá zmysel ukladať do medzipamäte a nulový.

Ale ak nulový hodnota znamená niečo vo vašom kóde, potom môžete dobre využiť Voliteľné trieda ako v nasledujúcom príklade:

@Test public void whenNullValue_thenOptional () {CacheLoader nakladač; loader = nový CacheLoader() {@Override public Optional load (String key) {return Optional.fromNullable (getSuffix (key)); }}; LoadingCache keška; cache = CacheBuilder.newBuilder (). build (nakladač); assertEquals ("txt", cache.getUnchecked ("text.txt"). get ()); assertFalse (cache.getUnchecked ("ahoj"). isPresent ()); } private String getSuffix (final String str) {int lastIndex = str.lastIndexOf ('.'); if (lastIndex == -1) {return null; } návrat str.substring (lastIndex + 1); }

7. Obnovte vyrovnávaciu pamäť

Ďalej sa pozrime, ako obnoviť naše hodnoty medzipamäte.

7.1. Ručné obnovenie

Jeden kľúč môžeme obnoviť manuálne pomocou LoadingCache.refresh (kľúč).

Reťazcová hodnota = loadingCache.get ("kľúč"); loadingCache.refresh ("kľúč");

Toto prinúti CacheLoader načítať novú hodnotu pre kľúč.

Kým sa nová hodnota úspešne načíta, predchádzajúca hodnota kľúč vráti dostať (kľúč).

7.2. Automatické obnovenie

Môžeme použiť CacheBuilder.refreshAfterWrite (trvanie) na automatické obnovenie hodnôt uložených v pamäti.

@Test public void whenLiveTimeEnd_thenRefresh () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder () .refreshAfterWrite (1, TimeUnit.MINUTES) .build (nakladač); }

Je dôležité to pochopiť refreshAfterWrite (trvanie) robí iba kľúč spôsobilý na obnovenie po zadanom trvaní. Hodnota sa v skutočnosti obnoví, až keď bude na príslušný záznam zadaný dopyt dostať (kľúč).

8. Predbežne načítajte vyrovnávaciu pamäť

Do našej medzipamäte môžeme vložiť viac záznamov pomocou putAll () metóda. V nasledujúcom príklade pridávame do našej medzipamäte viac záznamov pomocou a Mapa:

@Test public void whenPreloadCache_thenUsePutAll () {CacheLoader loader; loader = nový CacheLoader () {@Override verejné načítanie reťazca (kľúč reťazca) {návratový kľúč.toUpperCase (); }}; LoadingCache cache; cache = CacheBuilder.newBuilder (). build (nakladač); Mapová mapa = nová HashMap (); map.put ("prvý", "PRVÝ"); map.put ("druhý", "DRUHÝ"); cache.putAll (mapa); assertEquals (2, cache.size ()); }

9. Oznámenie o odstránení

Niekedy je potrebné vykonať určité kroky, keď sa záznam odstráni z medzipamäte; tak poďme diskutovať OdstránenieOznámenie.

Môžeme zaregistrovať a RemovalListener dostávať oznámenia o odstránení záznamu. Máme tiež prístup k príčine odstránenia - prostredníctvom servera getCause () metóda.

V nasledujúcej vzorke a OdstránenieOznámenie je prijatý, keď štvrtý prvok v pamäti cache z dôvodu jeho veľkosti:

@Test public void whenEntryRemovedFromCache_thenNotify () {CacheLoader loader; loader = new CacheLoader () {@Override verejné načítanie reťazca (konečný kľúč reťazca) {návratový kľúč.toUpperCase (); }}; Poslucháč RemovalListener; listener = new RemovalListener () {@Override public void onRemoval (RemovalNotification n) {if (n.wasEvicated ()) {Príčina reťazca = n.getCause (). name (); assertEquals (RemovalCause.SIZE.toString (), príčina); }}}; LoadingCache cache; cache = CacheBuilder.newBuilder () .maximumSize (3) .removalListener (poslucháč) .build (nakladač); cache.getUnchecked ("prvý"); cache.getUnchecked ("druhý"); cache.getUnchecked ("tretí"); cache.getUnchecked ("posledný"); assertEquals (3, cache.size ()); }

10. Poznámky

Na záver uvádzam niekoľko ďalších rýchlych poznámok o implementácii vyrovnávacej pamäte Guava:

  • je bezpečný pre vlákna
  • môžete hodnoty vložiť ručne do medzipamäte pomocou put (kľúč, hodnota)
  • môžete merať výkon svojej medzipamäte pomocou CacheStats ( hitRate (), missRate (), ..)

11. Záver

V tomto tutoriáli sme prešli mnohými prípadmi použitia vyrovnávacej pamäte Guava - od jednoduchého použitia po vysťahovanie prvkov, obnovenie a predbežné načítanie vyrovnávacej pamäte a oznámenia o odstránení.

Všetky príklady ako obvykle nájdete na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found