2014-06-08 77 views
0

我实现了一个Object缓存,像这样:的Java:对垃圾收集赛车

// Dictionary with weak keys & values 
private Map<Object, WeakReference<Object>> cache = new WeakHashMap<>(); 

private Object checkCache(Object obj) { 

    // If it's in the cache, returned the cached copy. 
    if (cache.containsKey(obj)) return cache.get(obj).get(); 

    // Store it in, and return it. 
    cache.put(obj, new WeakReference<>(obj)); 
    return obj; 
} 

图片下面的比赛条件的场景:

  1. cache.containsKey(obj)回报true
  2. 垃圾收集器开始并收集缓存中的对象。
  3. null被返回。

的问题是:

  • 可这真的会发生? AFAIK GC可以在任何时间踢任何时间。
  • Java GC可以禁用单个方法调用吗?​​似乎不能阻止GC。
  • 是否有任何解决方法?

在此先感谢!

+0

您正在滥用'WeakHashMap'。 – SLaks

+0

@SLaks请你详细说明为什么? – MBlanc

+0

在这种情况下,您既有弱键也有弱值。 –

回答

1

这真的会发生吗?

是。

Java GC可以禁用单个方法调用吗?

是否有任何变通办法?

是:试图从缓存中检索(从而建立如果它仍然在高速缓存中的强引用)的对象,并添加到缓存中如果引用是null

WeakReference<Object> ref = cache.get(obj); 
Object cached = (ref != null) ? ref.get() : null; 
if (cached != null) { 
    return cached; 
} 
else { 
    cache.put(obj, new WeakReference(obj)); 
    return obj; 
} 

您仍然需要同步方法,否则可能会有两个线程同时更新缓存(并且生成的update race将是least of your worries)。

0

是否需要WeakHashMap和WeakReference?你可以使用普通的HashMap和普通的键,然后使用一个定时器线程来清除HashMap中的旧值。 GC是相当不可预知的,所以除非你不介意在你的地图中有空值,我建议使用普通的值。

对于并发性,请看Java 7 Lock接口。就控制和性能而言,它比同步方法好得多。检查此区块是否有关于Java Lock Example and Concurrency Lock vs synchronized