מטמון גויאבה

1. סקירה כללית

במדריך זה, נסתכל על ה- מטמון גויאבה יישום - שימוש בסיסי, מדיניות פינוי, רענון המטמון וכמה פעולות מעניינות בתפזורת.

לבסוף, נסתכל על השימוש בהתראות ההסרה שמטמון מסוגל לשלוח.

2. כיצד להשתמש במטמון גויאבה

נתחיל בדוגמה פשוטה - בואו נאחסן במטמון את צורת האותיות הגדולות של חוּט מקרים.

ראשית, ניצור את מטמון מטמון - משמש לחישוב הערך המאוחסן במטמון. מכאן נשתמש בהישג יד CacheBuilder לבניית המטמון שלנו תוך שימוש במפרט הנתון:

@ מבחן ציבורי בטל כאשר CacheMiss_thenValueIsComputed () מטעין {CacheLoader; loader = CacheLoader חדש () {@Override ציבורית מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; מטמון = CacheBuilder.newBuilder (). build (מטעין); assertEquals (0, cache.size ()); assertEquals ("HELLO", cache.getUnchecked ("שלום")); assertEquals (1, cache.size ()); }

שימו לב כיצד אין ערך במטמון למפתח "שלום" שלנו - וכך הערך מחושב ושומר במטמון.

שים לב גם שאנחנו משתמשים ב- getUnchecked () פעולה - פעולה זו מחשבת ומטעינה את הערך במטמון אם הוא עדיין לא קיים.

3. מדיניות פינוי

כל מטמון צריך להסיר ערכים בשלב כלשהו. בואו נדון במנגנון של פינוי ערכים מהמטמון - תוך שימוש בקריטריונים שונים.

3.1. פינוי לפי גודל

אנחנו יכולים להגביל את גודל המטמון שלנו באמצעות maximumSize (). אם המטמון יגיע לגבול, הפריטים העתיקים ביותר יפונו.

בקוד הבא אנו מגבילים את גודל המטמון לשלושה רשומות:

@ מבחן ציבורי בטל כאשר CacheReachMaxSize_thenEviction () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבור מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; טעינת מטמון מטמון; cache = CacheBuilder.newBuilder (). maximumSize (3) .build (loader); cache.getUnchecked ("ראשון"); cache.getUnchecked ("שנייה"); cache.getUnchecked ("שלישי"); cache.getUnchecked ("הלאה"); assertEquals (3, cache.size ()); assertNull (cache.getIfPresent ("ראשון")); assertEquals ("FORTH", cache.getIfPresent ("קדימה")); }

3.2. פינוי לפי משקל

אנחנו יכולים גם להגביל את גודל המטמון באמצעות פונקציית משקל מותאמת אישית. בקוד הבא אנו משתמשים ב- אורך כפונקציית המשקל המותאמת אישית שלנו:

@ מבחן ציבורי בטל כאשר CacheReachMaxWeight_thenEviction () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבורית מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; Weigher weighByLength; weighByLength = משקל חדש () {@Override public int weigh (מפתח מחרוזת, ערך מחרוזת) {return value.length (); }}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder () .maximumWeight (16) .weigher (weighByLength) .build (loader); cache.getUnchecked ("ראשון"); cache.getUnchecked ("שנייה"); cache.getUnchecked ("שלישי"); cache.getUnchecked ("אחרון"); assertEquals (3, cache.size ()); assertNull (cache.getIfPresent ("ראשון")); assertEquals ("LAST", cache.getIfPresent ("האחרון")); }

הערה: המטמון עשוי להסיר יותר מרשומה אחת כדי להשאיר מקום לגדול חדש.

3.3. פינוי לפי זמן

בנוסף לשימוש בגודל לפינוי רשומות ישנות, אנו יכולים לנצל זמן. בדוגמה הבאה אנו מתאימים אישית את המטמון שלנו ל- הסר רשומות שהיו בטלות במשך 2ms:

@Test הציבור בטל כאשרEntryIdle_thenEviction () זורק את InterruptedException {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבורית מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder () .expireAfterAccess (2, TimeUnit.MILLISECONDS) .build (מטעין); cache.getUnchecked ("שלום"); assertEquals (1, cache.size ()); cache.getUnchecked ("שלום"); Thread.sleep (300); cache.getUnchecked ("מבחן"); assertEquals (1, cache.size ()); assertNull (cache.getIfPresent ("שלום")); }

אנחנו יכולים גם לפנות רשומות על סמך זמן החי הכולל שלהם. בדוגמה הבאה, המטמון יסיר את הרשומות לאחר האחסון של 2 שניות:

@Test ציבורי בטל כאשרEntryLiveTimeExpire_thenEviction () זורק InterruptedException {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבור מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder () .expireAfterWrite (2, TimeUnit.MILLISECONDS) .build (מטעין); cache.getUnchecked ("שלום"); assertEquals (1, cache.size ()); Thread.sleep (300); cache.getUnchecked ("מבחן"); assertEquals (1, cache.size ()); assertNull (cache.getIfPresent ("שלום")); }

4. מקשים חלשים

לאחר מכן, בואו נראה כיצד לגרום למפתחות המטמון שלנו להיות בעלי אזכורים חלשים - מה שמאפשר לאוסף הזבל לאסוף מפתחות מטמון שלא מופנים במקומות אחרים.

כברירת מחדל, למפתחות המטמון ולערכים יש הפניות חזקות אך אנו יכולים לגרום למטמון לאחסן את המפתחות באמצעות הפניות חלשות באמצעות מפתחות חלשים () כמו בדוגמה הבאה:

@Test הציבור בטל כאשר SweakKeyHasNoRef_thenRemoveFromCache () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבורית מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; מטמון = CacheBuilder.newBuilder (). חלש מפתחות (). build (מטעין); }

5. ערכים רכים

אנו יכולים לאפשר לאוסף הזבל לאסוף את ערכי המטמון באמצעות softValues ​​() כמו בדוגמה הבאה:

@ מבחן ציבורי בטל כאשר SoftValue_thenRemoveFromCache () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבור מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder (). softValues ​​(). build (loader); }

הערה: הפניות רכות רבות עשויות להשפיע על ביצועי המערכת - עדיף להשתמש בה maximumSize ().

6. ידית ריק ערכים

עכשיו, בואו נראה איך לטפל במטמון ריק ערכים. כברירת מחדל, מטמון גויאבה ישליך חריגים אם תנסה לטעון א ריק ערך - מכיוון שלא הגיוני למטמון a ריק.

אבל אם ריק ערך פירושו משהו בקוד שלך, ואז אתה יכול לעשות שימוש טוב ב- אופציונאלי בכיתה כמו בדוגמה הבאה:

@Test הציבור בטל כאשר NullValue_thenOptional () {CacheLoader מטעין; מטעין = CacheLoader חדש() {@ עקירה ציבורית עומס אופציונלי (מפתח מחרוזת) {החזרה Optional.fromNullable (getSuffix (מפתח)); }}; טעינת מטמון מטמון; מטמון = CacheBuilder.newBuilder (). build (מטעין); assertEquals ("txt", cache.getUnchecked ("text.txt"). get ()); assertFalse (cache.getUnchecked ("שלום"). isPresent ()); } מחרוזת פרטית getSuffix (מחרוזת מחרוזת סופית) {int lastIndex = str.lastIndexOf ('.'); אם (lastIndex == -1) {return null; } להחזיר str.substring (lastIndex + 1); }

7. רענן את המטמון

לאחר מכן, בואו נראה כיצד לרענן את ערכי המטמון שלנו.

7.1. רענון ידני

אנו יכולים לרענן מפתח יחיד באופן ידני בעזרת LoadingCache.refresh (מפתח).

ערך מחרוזת = loadingCache.get ("מפתח"); loadingCache.refresh ("מפתח");

זה יאלץ את מטמון מטמון כדי לטעון את הערך החדש עבור ה- מַפְתֵחַ.

עד שהערך החדש נטען בהצלחה, הערך הקודם של מַפְתֵחַ יוחזר על ידי להשיג מפתח).

7.2. רענון אוטומטי

אנחנו יכולים להשתמש CacheBuilder.refreshAfterWrite (משך) כדי לרענן באופן אוטומטי ערכים במטמון.

@Test ציבורי בטל whenLiveTimeEnd_thenRefresh () {מטעין מטמון מטעין; loader = CacheLoader חדש () {@Override ציבור מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder () .refreshAfterWrite (1, TimeUnit.MINUTES) .build (מטעין); }

חשוב להבין זאת refreshAfterWrite (משך) רק עושה מפתח זכאי לרענון לאחר משך הזמן שצוין. הערך יתרענן בפועל רק כאשר תשאול רשומה מתאימה להשיג מפתח).

8. טען מראש את המטמון

אנו יכולים להוסיף מספר רשומות במטמון באמצעות putAll () שיטה. בדוגמה הבאה, אנו מוסיפים רשומות מרובות למטמון באמצעות a מַפָּה:

@Test ציבורי בטל כאשרPreloadCache_thenUsePutAll () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבורית מחרוזת עומס (מפתח מחרוזת) {return key.toUpperCase (); }}; מטמון טעינת מטמון; מטמון = CacheBuilder.newBuilder (). build (מטעין); מפת מפה = HashMap חדש (); map.put ("ראשון", "FIRST"); map.put ("שנייה", "SECOND"); cache.putAll (מפה); assertEquals (2, cache.size ()); }

9. הסרת הודעה

לפעמים, אתה צריך לבצע כמה פעולות כאשר רשומה מוסרת מהמטמון; אז בואו נדבר הסרת הודעה.

אנחנו יכולים לרשום א RemovalListener כדי לקבל התראות על הסרת רשומה. יש לנו גם גישה לסיבת ההסרה - דרך getCause () שיטה.

במדגם הבא, א הסרת הודעה מתקבל כאשר האלמנט הרביעי במטמון בגלל גודלו:

@Test ציבורי בטל כאשרEntryRemovedFromCache_thenNotify () {מטעין CacheLoader; loader = CacheLoader חדש () {@Override ציבורי עומס מחרוזת (מפתח מחרוזת סופי) {return key.toUpperCase (); }}; מאזין RemovalListener; מאזין = RemovalListener חדש () {@ ביטול ציבורי ריק על הסרה (RemovalNotification n) {אם (n.wasEvicted ()) {סיבה מחרוזת = n.getCause (). שם (); assertEquals (RemovalCause.SIZE.toString (), סיבה); }}}; מטמון טעינת מטמון; cache = CacheBuilder.newBuilder () .maximumSize (3) .removalListener (מאזין) .build (מטעין); cache.getUnchecked ("ראשון"); cache.getUnchecked ("שנייה"); cache.getUnchecked ("שלישי"); cache.getUnchecked ("אחרון"); assertEquals (3, cache.size ()); }

10. הערות

לסיום, הנה כמה הערות מהירות נוספות על יישום המטמון של גויאבה:

  • זה חוט בטוח
  • אתה יכול להוסיף ערכים באופן ידני למטמון באמצעות לשים (מפתח, ערך)
  • אתה יכול למדוד את ביצועי המטמון באמצעות CacheStats ( אחוזי הצלחה(), missRate (), ..)

11. מסקנה

עברנו הרבה מקרים של שימוש במטמון הגויאבה במדריך זה - משימוש פשוט ועד פינוי אלמנטים, רענון וטעינה מוקדמת של המטמון והודעות הסרה.

כרגיל, ניתן למצוא את כל הדוגמאות ב- GitHub.