2016-05-31 77 views
0

我想要做這樣的事情:weakValues()和expireAfterAccess()可以結合使用嗎?

CacheBuilder 
      .newBuilder() 
      .maximumSize(CONFIG.cacheMaxSize()) 
      .expireAfterAccess(CONFIG.cacheTimeout(), 
           CONFIG.cacheTimeUnit()) 
      .weakValues() 
      .build(cacheLoader); 

我期望的行爲是一個條目將僅值未引用和有效期已過到期。這是怎麼用的?

回答

2

不是直接的,因爲弱者值可以被垃圾收集只要沒有更強烈的對象引用。然而,你可以做的是使用ForwardingCache,它由兩個單獨的緩存,一個弱值緩存和一個定時到期的緩存支持,以便基於時間的緩存保持對該對象的強引用,從而將其保留在弱值緩存中。它會是這個樣子:

public class WeakValuedExpiringCache<K, V> extends ForwardingCache<K, V> { 
    private final Cache<K, V> expiringCache; 
    private final Cache<K, V> weakCache; 

    public WeakValuedExpiringCache(CacheBuilder expiringSpec) { 
    expiringCache = expiringSpec.build(); 
    weakCache = CacheBuilder.newBuilder().weakValues().build(); 
    } 

    // weakCache is the canonical cache since it will hold values longer than 
    // expiration if there remain other strong references 
    protected Cache<K, V> delagate() { 
    return weakCache; 
    } 

    @override 
    public V get(K key, Callable<? extends V> valueLoader) 
    throws ExecutionException { 
    // repopulate the expiring cache if needed, and update the weak cache 
    V value = expiringCache.get(key, valueLoader); 
    weakCache.put(key, value); // don't call super.put() here 
    } 

    @Override 
    public void put(K key, V value) { 
    expiringCache.put(key, value); 
    super.put(key, value); 
    } 

    // Handle putAll(), cleanUp(), invalidate(), and invalidateAll() similarly 
} 

你可以做同樣的事情用ForwardingLoadingCache爲好,就像上面.get()你應該從expiringCache.put()它的價值裝入weakCache在相關的裝載方法。

+0

謝謝!那很完美。你看到我的問題,我的意思是應該沒有其他引用的價值BESIDES緩存。我沒有想過,一個弱引用不會阻止gc。 – jacob

1

沒有,一個條目將到期,如果該值不引用或到期時間已經過去了:

public class CacheBuilderIT { 
    @Test 
    public void expireAfterAccessWithWeakValues() throws InterruptedException { 
     Cache<Object, Object> cache = CacheBuilder.newBuilder() 
       .expireAfterAccess(500, MILLISECONDS) 
       .weakValues() 
       .build(); 
     Object key = new Object(); 
     Object value = new Object(); // keep a strong reference to the value 
     cache.put(key, value); 
     Thread.sleep(300); 
     assert cache.getIfPresent(key) != null : "expiration occurred too quickly"; 
     Thread.sleep(300); 
     assert cache.getIfPresent(key) != null : "last access did not reset expiration"; 
     Thread.sleep(1000); 
     assert cache.getIfPresent(key) != null : "reference did not prevent expiration"; 
    } 
} 

Ouptut:

java.lang.AssertionError: reference did not prevent expiration 
+0

非常感謝! – jacob

相關問題