Guava缓存器源码分析——数据加载
2013-09-17 13:38
495 查看
Guava缓存器加载数据的方式有两种:同步(loadSync)与异步(loadAsync)。
同步方式——
只在取数据 V get(K, int, CacheLoader)执行过程中会被调用到。
同步加载数据代码如下:
ListenableFuture<V> loadingFuture = loadingValueReference.loadFuture(key, loader);
return getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
异步方式——
只在刷新数据refresh(K, int, CacheLoader, boolean)执行过程中会被调用到。
guava缓存器没有提供类似refreshAll()的方法来刷新所有值,而只是提供了 refresh(Key)的方法来刷新某个键值对,这里的刷新动作是异步执行的,如果有人在值被彻底刷新之前,取这个Key的值,返回的还是刷新前的值。
在执行refresh时,会调用loadAsync方法来异步加载数据,同时通过isDone()方法来判断任务是否完成,正常结束、异常或者是被取消,这个方法都会返回true。
ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
if (result.isDone()) {
try {
return Uninterruptibles.getUninterruptibly(result);
} catch (Throwable t) {
}
}
return null;
不管是同步或异步方式,都会调用到loadFuture(key, loader)方法,先将数据取到。
loadFuture执行流程:
1、取key对应的旧值;
2、旧值不存在,则调用load方法取新值。
3、通过futureValue的set方法来设置新值,成功则返回futureValue,否则返回Futures.immediateFuture(newValue)。
4、旧值存在,则调用reload方法重取新值。
5、reload方法返回类型为ListenableFuture<V>,结果不为null则直接返回,否则返回 Futures.<V>immediateFuture(null)。
Futures的immediateFuture方法,返回了一个ImmediateSuccessfulFuture对象,在其构造函数中初始化值,该Future不能被取消或超时,它的isDone()方法只返回true。
![](http://img.blog.csdn.net/20130917134826906?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRGVzaWx0aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
异步方式,在取数完成后,将注册一个监听器,完成数据的最终加载并统计信息。
loadingFuture.addListener(
new Runnable() {
@Override
public void run() {
try {
V newValue = getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
loadingValueReference.set(newValue);
} catch (Throwable t) {
logger.log(Level.WARNING, "Exception thrown during refresh", t);
loadingValueReference.setException(t);
}
}
}, sameThreadExecutor);
涉及的类:
![](http://img.blog.csdn.net/20130917135026156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRGVzaWx0aW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这部分代码,通过Runnable接口实现,没有返回结果。
其中SettableFuture通过set(Object)或setException(Throwable)来设置值。
AbstractFuture类通过AbstractQueuedSynchronizer来处理同步问题和保证线程安全。所有涉及状态改变的方法,都会返回一个boolean值来表明状态改变是否成功,有效的状态有running, completed, failed, cancelled。这个类通过ExecutionList来保证当Future结束时所有注册的监听器,或完成后添加的监听器都能被执行。Runnable-Executor对存放在execution列表中,但不一定按它们添加的顺序执行,如果一个监听器在Future结束后添加,它将被立即执行,就算在它之前的监听器还没执行。
如果需要知道返回结果,可以使用Guava提供的ListenableFutureTask类,该类继承至FutureTask并实现了ListenableFuture接口, 可自由选择实现Runnable的void run()方法,或Callable的 V call()方法(有返回结果),这几个类看的不够仔细,需要再研究。
同步方式——
只在取数据 V get(K, int, CacheLoader)执行过程中会被调用到。
同步加载数据代码如下:
ListenableFuture<V> loadingFuture = loadingValueReference.loadFuture(key, loader);
return getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
异步方式——
只在刷新数据refresh(K, int, CacheLoader, boolean)执行过程中会被调用到。
guava缓存器没有提供类似refreshAll()的方法来刷新所有值,而只是提供了 refresh(Key)的方法来刷新某个键值对,这里的刷新动作是异步执行的,如果有人在值被彻底刷新之前,取这个Key的值,返回的还是刷新前的值。
在执行refresh时,会调用loadAsync方法来异步加载数据,同时通过isDone()方法来判断任务是否完成,正常结束、异常或者是被取消,这个方法都会返回true。
ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
if (result.isDone()) {
try {
return Uninterruptibles.getUninterruptibly(result);
} catch (Throwable t) {
}
}
return null;
不管是同步或异步方式,都会调用到loadFuture(key, loader)方法,先将数据取到。
loadFuture执行流程:
1、取key对应的旧值;
2、旧值不存在,则调用load方法取新值。
3、通过futureValue的set方法来设置新值,成功则返回futureValue,否则返回Futures.immediateFuture(newValue)。
4、旧值存在,则调用reload方法重取新值。
5、reload方法返回类型为ListenableFuture<V>,结果不为null则直接返回,否则返回 Futures.<V>immediateFuture(null)。
Futures的immediateFuture方法,返回了一个ImmediateSuccessfulFuture对象,在其构造函数中初始化值,该Future不能被取消或超时,它的isDone()方法只返回true。
异步方式,在取数完成后,将注册一个监听器,完成数据的最终加载并统计信息。
loadingFuture.addListener(
new Runnable() {
@Override
public void run() {
try {
V newValue = getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
loadingValueReference.set(newValue);
} catch (Throwable t) {
logger.log(Level.WARNING, "Exception thrown during refresh", t);
loadingValueReference.setException(t);
}
}
}, sameThreadExecutor);
涉及的类:
这部分代码,通过Runnable接口实现,没有返回结果。
其中SettableFuture通过set(Object)或setException(Throwable)来设置值。
AbstractFuture类通过AbstractQueuedSynchronizer来处理同步问题和保证线程安全。所有涉及状态改变的方法,都会返回一个boolean值来表明状态改变是否成功,有效的状态有running, completed, failed, cancelled。这个类通过ExecutionList来保证当Future结束时所有注册的监听器,或完成后添加的监听器都能被执行。Runnable-Executor对存放在execution列表中,但不一定按它们添加的顺序执行,如果一个监听器在Future结束后添加,它将被立即执行,就算在它之前的监听器还没执行。
如果需要知道返回结果,可以使用Guava提供的ListenableFutureTask类,该类继承至FutureTask并实现了ListenableFuture接口, 可自由选择实现Runnable的void run()方法,或Callable的 V call()方法(有返回结果),这几个类看的不够仔细,需要再研究。
相关文章推荐
- Launcher3源码分析(LauncherModel加载数据)
- ViewPager部分源码分析一:加载数据
- Launcher3源码分析 — 加载Workspace的数据
- Launcher3源码分析 — 所有应用页面的数据加载和绑定
- nhibernate源码分析之七: HQL数据加载
- Launcher3源码分析 — 加载Workspace的数据 .
- Launcher3源码分析 — 加载Workspace的数据
- Android 7.0 Gallery图库源码分析3 - 数据加载及显示流程
- nhibernate源码分析之六: Criteria数据加载
- 从源码的角度分析Volley加载数据的过程
- Giraph 源码分析(五)—— 加载数据+同步总结
- Launcher3源码分析 — 数据加载过程
- Launcher3源码分析 — 数据加载过程
- 为什么Spring的HibernateTemplate一般情况下不支持数据的惰性加载的源码分析
- nhibernate源码分析之六: Criteria数据加载
- Fresco 源码分析(四) 后台数据返回到前台的处理 - Drawable体系的介绍(1)
- React实战-通过ToDo源码分析Redux的数据模型设计
- 关于android 的数据开关项源码分析
- 数据结构与算法学习(二)链式存储结构LinkedList源码分析
- 【Netty源码分析】发送数据过程