Guava Cache是性能非常高的本地缓存,其他的还有ehcache等。相对于本地缓存还有分布式缓存,其实就是独立于业务的第三方应用,比如redis、memcahe或者自己弄个机器加大内存,把它当作另外一个集群的分布式缓存同样是可以的,但是要做到高可用不是一件简单的事情。另外,内存缓存有个不可避免的问题是易丢失,所以要持久化的就老老实实弄一个redis或者直接入库。这里主要记录是标题的内容,话不多直接开始,先是使用,然后在看builder,学习谷歌大神写的代码得分好篇文章了,这篇文章主要就是上述两者:
Guava Cache的使用
使用相对简单,这也是它流传广泛的一个重要原因吧,直接上平时使用的代码:
public LoadingCache<String, String> serviceCache =
CacheBuilder.newBuilder().maximumSize(20000).expireAfterWrite(10, TimeUnit.SECONDS)
.recordStats().build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
return service.query(key);
}
});
Builder
这里我们可以看到LoadingCache是通过newBuilder的方式建立的,这里用到的是Builder设计模式,先看上构建cache的类似实现,这是摘自这篇文章的一个例子,这个很好理解,一个bean中有个静态内部类Builder,其中的属性就是外部person对应的属性,它对外暴露属性,并把返回Buildler自身,直到使用bulid(),new出外部类。
/**
* @author SunKing1927 2015年11月2日
* Java Builder模式
*/
public class Person {
private String name;
private int age;
private boolean sex;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isSex() {
return sex;
}
public static class Builder {
private String name;
private int age;
private boolean sex;
public Builder name(String n) {
name = n;
return this;
}
public Builder age(int a) {
age = a;
return this;
}
public Builder sex(boolean s) {
sex = s;
return this;
}
public Person build() {
return new Person(this);
}
}
private Person(Builder builder) {
name = builder.name;
age = builder.age;
sex = builder.sex;
}
}
下边看一下经典的Builder是如何实现的,下边是UML类图
从上图可以看到,经典Buider模式中有四个角色:
1、要建造的产品Product -- LoadingCache
2、抽象的Builder -- 我们的例子中略去了抽象层,我们可以随时抽象
3、Builder的具体实现ConcreteBuilder -- 对应maximumSize、expireAfterWrite等
4、使用者Director -- 对应的类
有了上述的这些点,我们来看下guava cache的Builder代码的实现,首先是创建一个CacheBuilder
/**
* 静态公共方法暴露出来进行构建
*/
public static CacheBuilder<Object, Object> newBuilder() {
return new CacheBuilder<Object, Object>();
}
剩下的就是利用各种属性进行赋值,我们这里只使用其中一个作为例子
/**
* 1、对参数进行校验
* 2、赋值之后返回CacheBuilder对象本身,和上边的Person本身是很想的
*/
public CacheBuilder<K, V> maximumSize(long size) {
checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
this.maximumSize);
checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s",
this.maximumWeight);
checkState(this.weigher == null, "maximum size can not be combined with weigher");
checkArgument(size >= 0, "maximum size must not be negative");
this.maximumSize = size;
return this;
}
public CacheBuilder<K, V> expireAfterWrite(long duration, TimeUnit unit) {
checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns",
expireAfterWriteNanos);
checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit);
this.expireAfterWriteNanos = unit.toNanos(duration);
return this;
}
第三步就是调用build()方法进行构建LocalCache类
/**
* 1、LocalCache调用其静态内部类LocalLoadingCache的构造方法new了一个LocalCache,这一点和上边的person很像
*/
public <K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
CacheLoader<? super K1, V1> loader) {
checkWeightWithWeigher();
return new LocalCache.LocalLoadingCache<K1, V1>(this, loader);
}
static class LocalLoadingCache<K, V>
extends LocalManualCache<K, V> implements LoadingCache<K, V> {
LocalLoadingCache(CacheBuilder<? super K, ? super V> builder,
CacheLoader<? super K, V> loader) {
super(new LocalCache<K, V>(builder, checkNotNull(loader)));
}
}
/**
* new LocalCache的过程就是把builder中的属性赋值到LocalCache中属性的过程
*/
LocalCache(
CacheBuilder<? super K, ? super V> builder, @Nullable CacheLoader<? super K, V> loader) {
concurrencyLevel = Math.min(builder.getConcurrencyLevel(), MAX_SEGMENTS);
keyStrength = builder.getKeyStrength();
valueStrength = builder.getValueStrength();
keyEquivalence = builder.getKeyEquivalence();
valueEquivalence = builder.getValueEquivalence();
maxWeight = builder.getMaximumWeight();
weigher = builder.getWeigher();
expireAfterAccessNanos = builder.getExpireAfterAccessNanos();
expireAfterWriteNanos = builder.getExpireAfterWriteNanos();
refreshNanos = builder.getRefreshNanos();
removalListener = builder.getRemovalListener();
removalNotificationQueue = (removalListener == NullListener.INSTANCE)
? LocalCache.<RemovalNotification<K, V>>discardingQueue()
: new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
ticker = builder.getTicker(recordsTime());
entryFactory = EntryFactory.getFactory(keyStrength, usesAccessEntries(), usesWriteEntries());
globalStatsCounter = builder.getStatsCounterSupplier().get();
defaultLoader = loader;
int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY);
if (evictsBySize() && !customWeigher()) {
initialCapacity = Math.min(initialCapacity, (int) maxWeight);
}
CacheLoader是一个抽象类,第一个例子中返回了它的一个实现
/**
* CacheLoader是一个抽象类,返回的是CacheLoader的一个实现,至于其中的方法什么时候调用,完全看localCache的需要
*/
new CacheLoader<String, String>() {
@Override
public String load(String key) {
return service.query(key);
}
}
至此guava localcache对象便生成了,嗯,这只是很简单的第一步。