谢谢大家 ,尤其是对提出这个想法的用户“ gid ”。
我的目标是考虑到invalidate() *** 作将被称为非常罕见,从而优化get() *** 作的性能。
我编写了一个测试类,该类启动了16个线程,每个线程调用get()-Operation一百万次。在本课程中,我介绍了我的2核机器的一些实现。
测试结果
Implementation Timeno synchronisation 0,6 secnormal synchronisation 7,5 secwith MapMaker 26,3 secwith Suppliers.memoize 8,2 secwith optimized memoize 1,5 sec
1)“不同步”不是线程安全的,但它为我们提供了可以与之相比的最佳性能。
@Overridepublic List<String> list() { if (cache == null) { cache = loadCountryList(); } return cache;}@Overridepublic void invalidateCache() { cache = null;}
2)“正常同步”-相当不错的性能,标准的轻松实现
@Overridepublic synchronized List<String> list() { if (cache == null) { cache = loadCountryList(); } return cache;}@Overridepublic synchronized void invalidateCache() { cache = null;}
3)“使用MapMaker”-性能非常差。
有关代码,请参见顶部的问题。
4)“与Suppliers.memoize”-良好的表现。但是,对于性能相同的“常规同步”,我们需要对其进行优化,或者仅使用“常规同步”。
有关代码,请参见用户“ gid”的答案。
5) “具有优化 的备忘 ” -与“不同步”实现相当的性能,但具有线程安全性。这是我们需要的。
缓存类本身:(此处使用的Supplier接口来自Google Collections
Library,它只有一种get()方法。请参见http://google-
collections.googlepre.com/svn/trunk/javadoc/com/google/ common / base /
Supplier.html)
public class LazyCache<T> implements Supplier<T> { private final Supplier<T> supplier; private volatile Supplier<T> cache; public LazyCache(Supplier<T> supplier) { this.supplier = supplier; reset(); } private void reset() { cache = new MemoizingSupplier<T>(supplier); } @Override public T get() { return cache.get(); } public void invalidate() { reset(); } private static class MemoizingSupplier<T> implements Supplier<T> { final Supplier<T> delegate; volatile T value; MemoizingSupplier(Supplier<T> delegate) { this.delegate = delegate; } @Override public T get() { if (value == null) { synchronized (this) { if (value == null) { value = delegate.get(); } } } return value; } }}
使用示例:
public class BetterMemoizeCountryList implements ICountryList { LazyCache<List<String>> cache = new LazyCache<List<String>>(new Supplier<List<String>>(){ @Override public List<String> get() { return loadCountryList(); } }); @Override public List<String> list(){ return cache.get(); } @Override public void invalidateCache(){ cache.invalidate(); } private List<String> loadCountryList() { // this should normally load a full list from the database, // but just for this instance we mock it with: return Arrays.asList("Germany", "Russia", "China"); }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)