V internalCreate(K key) {
try
{
FutureTask<V> futureTask =
new
FutureTask<V>(
new
CallableCreate(key));
Object keyReference = referenceKey(key);
Future<V> future =
futures
.putIfAbsent(keyReference, futureTask);
if
(future ==
null
) {
// winning thread.
try
{
/*
*同一线程的 一次插入操作还未完成,又来一次插入操作时便可能出现这种情况future==null 并且 localFuture.get()==null
* */
if
(
localFuture
.get() !=
null
) {
throw
new
IllegalStateException(
"Nested creations within the same cache are not allowed."
);
}
localFuture
.set(futureTask);
futureTask.run();
V value = futureTask.get();
putStrategy().execute(
this
,
keyReference, referenceValue(keyReference, value));
return
value;
}
finally
{
localFuture
.remove();
futures
.remove(keyReference);
}
}
else
{
// wait for winning thread.
return
future.get();
}
}
catch
(InterruptedException e) {
throw
new
RuntimeException(e);
}
catch
(ExecutionException e) {
Throwable cause = e.getCause();
if
(cause
instanceof
RuntimeException) {
throw
(RuntimeException) cause;
}
else
if
(cause
instanceof
Error) {
throw
(Error) cause;
}
throw
new
RuntimeException(cause);
}
}
上面是internalCreate方法的全部代码了,但从这里却没有看到有对create方法的调用。这里是通过引入FutureTask实现的,FutureTask代表了一类异步计算过程,并且提供了获取异步计算结果的方法,以及对计算状态进行检查的和取消计算的接口。在其构造函数之一中需要提供一个Callable对象作为参数,在调用FutureTask对象的get方法的时候,会调用这个参数对象的call方法,并且等待结果计算返回。
在上面代码中,
FutureTask<V> futureTask =
new
FutureTask<V>(
new
CallableCreate(key));构造出了一个futureTask对象,并且传递了一个CallableCreate对象,CallableCreate类是一个内部类,在ReferenceCache.java文件中,代码如下
class
CallableCreate
implements
Callable<V> {
K
key
;
public
CallableCreate(K key) {
this
.
key
= key;
}
public
V call() {
// try one more time (a previous future could have come and gone.)
V value = internalGet(
key
);
if
(value !=
null
) {
return
value;
}
// using the key type to create one value
value = create(
key
);
if
(value ==
null
) {
throw
new
NullPointerException(
"create(K) returned null for: "
+
key
);
}
return
value;
}
}
call方法是实现的Callable的接口方法,在其中也实现尝试通过缓存获取数据,不存在时,通过value=create(key);来创建数据。就是在此处,调用了抽象方法create,也就是留个外界补充的入口。
再来回头看internalCreate方法,其实主要部分就是future.get()和futureTask.get()两句再起作用,其它的语句是一些相应的设置和判断过程。在get方法被调用的时候,在CallableCreate中实现的call方法会被调用,这个方法又转去调用create方法,从而实现了用户自动以地加载数据过程。
因此ReferenceCache中存在抽象函数,所以ReferenceCache类是一个抽象类,无法实例化对象,这就强制继承ReferenceCache类,并且实现crate方法。