TA的每日心情 | 开心 2021-12-13 21:45 |
---|
签到天数: 15 天 [LV.4]偶尔看看III
|
在某些情况下我们需要使用本地缓存来加载一些小型数据,比如说一些配置数据。如果去查Mysql或者redis数据库需要走网络协议。这些数据可以加载到内存随时供java程序调用。
接下来实现的是使用Google的guava实现本地缓存,另外需要提供给其它服务使用的话,还可以使用netty对外发布服务,netty远程服务将会在接下来的本章中总结。
1、 策略接口,每个策略都必须实现这个标签的策略接口
```java
public interface ILocalCache {
/**
* 根据key获取value
* @param k key
* @return value
*/
V get(K k);
/**
* 设置k和v的值
* @param k
* @param v
*/
void set(K k,V v);
}
```
2、 新建一个策略辅助类(封装了对Guava Cache的利用,包括cache的创建,从数据源获取数据,设置K,V等)
```java
public abstract class GuavaAbstractCache {
private int maximumSize = Integer.MAX_VALUE; // 最大缓存条目
private int expireAfterWriteDuration = 60*24; // 数据存在时长(一天)
private TimeUnit timeUnit = TimeUnit.MINUTES; // 时间单位(分钟)
private LoadingCache cache;
/**
* 通过调用getCache().get(key)来获取数据
* @return cache
*/
public LoadingCache getCache() {
if (cache == null) { // 使用双重校验锁保证只有一个cache实例
synchronized (this) {
if (cache == null) {
cache = CacheBuilder.newBuilder()
// 缓存数据的最大条目,也可以使用.maximumWeight(weight)代替
.maximumSize(maximumSize)
// 数据被创建多久后被移除 默认设置一天
.expireAfterWrite(expireAfterWriteDuration, timeUnit)
// 创建缓存使用fetchData
.build(new CacheLoader() {
@Override
public V load(K key) throws Exception {
return fetchData(key);
}
});
}
}
}
return cache;
}
/**
* 从缓存中获取数据(第一次自动调用fetchData从外部获取数据)
* @param key
* @return Value
* @throws ExecutionException
*/
protected V getValue(K key) throws ExecutionException {
V result = getCache().get(key);
return result;
}
/**
* 直接设置缓存数据到
* @param key
* @param value
*/
protected void setValue(K key,V value) throws ExecutionException {
getCache().put(key, value);
}
/**
* 根据key从数据库或其他数据源中获取一个value,
* 并被自动保存到缓存中。 这个方法由子类实现,
* 以达到不同策略从不同的数据源获取缓存信息的效果
* @param key
* @return value,连同key一起被加载到缓存中。
*/
protected abstract V fetchData(K key);
}
```
3、 实现一个加载文件中的标签数据的缓存类
```java
public class TagsCache extends GuavaAbstractCache implements ILocalCache {
public static final String TAGSKEY = "tags";
@Override
public Object get(String k) {
try {
return getValue(k);
} catch (Exception e) {
return null;
}
}
@Override
public void set(String k, Object v) {
try {
setValue(k, v);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected Object fetchData(String key) {
//如果是tags标签数据直接从文件里加载,每天加载一次
if (TAGSKEY.equals(key)) {
final File file = new File("/data/ids/tags.txt");
if(!file.exists()) {
CommonLog.error("标签文件不存在");
return null;
}
final Set tagsSet = new HashSet();
FileInputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
inputStream = new FileInputStream(file);
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String tag = "";
while ((tag = bufferedReader.readLine()) != null) {
if(StringUtils.isNotEmpty(tag)) {
tagsSet.add(tag);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return tagsSet;
}else if("aaaa".equals(key)) {
return "你好";
}
return null;
}
public static void main(String[] args) {
ILocalCache cache = new TagsCache();
System.out.println(cache.get("aaaa"));
cache.set("aaaa", "nihao");
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
System.out.println(cache.get("aaaa"));
}
}
```
4、 上面的main方法是设置缓存1秒钟过期的效果为:
```
你好
nihao
nihao
nihao
nihao
你好
你好
你好
你好
你好
``` |
|