缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。
创建缓存对象EntityCache.java
public
class
EntityCache {
/**
* 保存的数据
*/
private
Object datas;
/**
* 设置数据失效时间,为0表示永不失效
*/
private
long
timeOut;
/**
* 最后刷新时间
*/
private
long
lastRefeshTime;
public
EntityCache(Object datas,
long
timeOut,
long
lastRefeshTime) {
this
.datas = datas;
this
.timeOut = timeOut;
this
.lastRefeshTime = lastRefeshTime;
}
public
Object getDatas() {
return
datas;
}
public
void
setDatas(Object datas) {
this
.datas = datas;
}
public
long
getTimeOut() {
return
timeOut;
}
public
void
setTimeOut(
long
timeOut) {
this
.timeOut = timeOut;
}
public
long
getLastRefeshTime() {
return
lastRefeshTime;
}
public
void
setLastRefeshTime(
long
lastRefeshTime) {
this
.lastRefeshTime = lastRefeshTime;
}
}
定义缓存操作接口,ICacheManager.java
public
interface
ICacheManager {
/**
* 存入缓存
* @param key
* @param cache
*/
void
putCache(String key, EntityCache cache);
/**
* 存入缓存
* @param key
* @param cache
*/
void
putCache(String key, Object datas,
long
timeOut);
/**
* 获取对应缓存
* @param key
* @return
*/
EntityCache getCacheByKey(String key);
/**
* 获取对应缓存
* @param key
* @return
*/
Object getCacheDataByKey(String key);
/**
* 获取所有缓存
* @param key
* @return
*/
Map<String, EntityCache> getCacheAll();
/**
* 判断是否在缓存中
* @param key
* @return
*/
boolean
isContains(String key);
/**
* 清除所有缓存
*/
void
clearAll();
/**
* 清除对应缓存
* @param key
*/
void
clearByKey(String key);
/**
* 缓存是否超时失效
* @param key
* @return
*/
boolean
isTimeOut(String key);
/**
* 获取所有key
* @return
*/
Set<String> getAllKeys();
}
实现接口ICacheManager,CacheManagerImpl.java
这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。
public
class
CacheManagerImpl
implements
ICacheManager {
private
static
Map<String, EntityCache> caches =
new
ConcurrentHashMap<String, EntityCache>();
/**
* 存入缓存
* @param key
* @param cache
*/
public
void
putCache(String key, EntityCache cache) {
caches.put(key, cache);
}
/**
* 存入缓存
* @param key
* @param cache
*/
public
void
putCache(String key, Object datas,
long
timeOut) {
timeOut = timeOut >
0
? timeOut : 0L;
putCache(key,
new
EntityCache(datas, timeOut, System.currentTimeMillis()));
}
/**
* 获取对应缓存
* @param key
* @return
*/
public
EntityCache getCacheByKey(String key) {
if
(
this
.isContains(key)) {
return
caches.get(key);
}
return
null
;
}
/**
* 获取对应缓存
* @param key
* @return
*/
public
Object getCacheDataByKey(String key) {
if
(
this
.isContains(key)) {
return
caches.get(key).getDatas();
}
return
null
;
}
/**
* 获取所有缓存
* @param key
* @return
*/
public
Map<String, EntityCache> getCacheAll() {
return
caches;
}
/**
* 判断是否在缓存中
* @param key
* @return
*/
public
boolean
isContains(String key) {
return
caches.containsKey(key);
}
/**
* 清除所有缓存
*/
public
void
clearAll() {
caches.clear();
}
/**
* 清除对应缓存
* @param key
*/
public
void
clearByKey(String key) {
if
(
this
.isContains(key)) {
caches.remove(key);
}
}
/**
* 缓存是否超时失效
* @param key
* @return
*/
public
boolean
isTimeOut(String key) {
if
(!caches.containsKey(key)) {
return
true
;
}
EntityCache cache = caches.get(key);
long
timeOut = cache.getTimeOut();
long
lastRefreshTime = cache.getLastRefeshTime();
if
(timeOut ==
0
|| System.currentTimeMillis() - lastRefreshTime >= timeOut) {
return
true
;
}
return
false
;
}
/**
* 获取所有key
* @return
*/
public
Set<String> getAllKeys() {
return
caches.keySet();
}
}
CacheListener.java,监听失效数据并移除。
public
class
CacheListener{
Logger logger = Logger.getLogger(
"cacheLog"
);
private
CacheManagerImpl cacheManagerImpl;
public
CacheListener(CacheManagerImpl cacheManagerImpl) {
this
.cacheManagerImpl = cacheManagerImpl;
}
public
void
startListen() {
new
Thread(){
public
void
run() {
while
(
true
) {
for
(String key : cacheManagerImpl.getAllKeys()) {
if
(cacheManagerImpl.isTimeOut(key)) {
cacheManagerImpl.clearByKey(key);
logger.info(key +
"缓存被清除"
);
}
}
}
}
}.start();
}
}
测试类TestCache.java
public
class
TestCache {
Logger logger = Logger.getLogger(
"cacheLog"
);
/**
* 测试缓存和缓存失效
*/
@Test
public
void
testCacheManager() {
CacheManagerImpl cacheManagerImpl =
new
CacheManagerImpl();
cacheManagerImpl.putCache(
"test"
,
"test"
,
10
* 1000L);
cacheManagerImpl.putCache(
"myTest"
,
"myTest"
,
15
* 1000L);
CacheListener cacheListener =
new
CacheListener(cacheManagerImpl);
cacheListener.startListen();
logger.info(
"test:"
+ cacheManagerImpl.getCacheByKey(
"test"
).getDatas());
logger.info(
"myTest:"
+ cacheManagerImpl.getCacheByKey(
"myTest"
).getDatas());
try
{
TimeUnit.SECONDS.sleep(
20
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
logger.info(
"test:"
+ cacheManagerImpl.getCacheByKey(
"test"
));
logger.info(
"myTest:"
+ cacheManagerImpl.getCacheByKey(
"myTest"
));
}
/**
* 测试线程安全
*/
@Test
public
void
testThredSafe() {
final
String key =
"thread"
;
final
CacheManagerImpl cacheManagerImpl =
new
CacheManagerImpl();
ExecutorService exec = Executors.newCachedThreadPool();
for
(
int
i =
0
; i <
100
; i++) {
exec.execute(
new
Runnable() {
public
void
run() {
if
(!cacheManagerImpl.isContains(key)) {
cacheManagerImpl.putCache(key,
1
,
0
);
}
else
{
//因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来
synchronized
(cacheManagerImpl) {
int
value = (Integer) cacheManagerImpl.getCacheDataByKey(key) +
1
;
cacheManagerImpl.putCache(key,value ,
0
);
}
}
}
});
}
exec.shutdown();
try
{
exec.awaitTermination(
1
, TimeUnit.DAYS);
}
catch
(InterruptedException e1) {
e1.printStackTrace();
}
logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());
}
}
来源:http://www.jb51.net/article/111518.htm