使用Mapjava 实现缓存java缓存,但是如何从缓存中获取

java&利用Map做缓存一个简单实例
以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引,它们本身也是对象,这样非常像数组了,下面我们介绍map
缓存的实例。
有时候需要将一批数据缓存,并且按照最近最少使用的规则淘汰。这时候就应该想到LRUMap。
LRUMap是一种尺寸固定的Map,当它的容量达到最大时采用最近最少使用的规则淘汰相应的元素。
LRUMap cache = newLRUMap(5);&
cache.put("01", "news 1");&
cache.put("02", "news 2");&
cache.put("03", "news 3");&
cache.put("04", "news 4");&
cache.put("05", "news 5");&
String news1 = (String)cache.get("01");&
String news2 = (String)cache.get("02");&
String news3 = (String)cache.get("04");&
String news4 = (String)cache.get("03");&
String news5 = (String)cache.get("02");&
String news6 = (String)cache.get("05");&
cache.put("06", "news 6");&
Iterator it =
cache.entrySet().iterator();&
while(it.hasNext()){&
&& Map.Entry entry =
(Map.Entry)it.next();&
System.out.println(entry.getValue());&
LazyMap:当你需要获取某个键值但发现该键值不存在时自动填充该键值,那就该考虑使用LazyMap,LazyMap采用了装饰模式装饰一个Map,并采用一个Transformer来决定当键值不存在时填充的规则(或者Factory)。
Transformer reverseString =
newTransformer(){&
publicObject transform(Object object){&
&&&&&&&&&&
String name = (String)&
&&&&&&&&&&
String reverse =
StringUtils.reverse(name);&
&&&&&&&&&&
&&& Map names =
newHashMap();&
lazynames = LazyMap.decorate(names,
reverseString);&
System.out.println(lazynames.get("hello"));&
System.out.println(lazynames.get("thanks"));&
System.out.println(lazynames.get("not at
&&& Factory
factory = newFactory(){&
publicObject create(){&
&&&&&&&&&&
return"NB";&
&&& Map lazyname
= LazyMap.decorate(names, factory);&
System.out.println(lazyname.get("woshishei"));&
System.out.println(lazyname.get("nishishei"));&
System.out.println(lazyname.get("not at all"));
综合使用LRUMap和LazyMap:
Transformer reverseString =
newTransformer(){&
publicObject transform(Object object){&
&&&&&&&&&&
String name = (String)&
&&&&&&&&&&
String reverse =
StringUtils.reverse(name);&
&&&&&&&&&&
&&& LRUMap
lruMap = newLRUMap(5);&
&&& Map lazyMap
= LazyMap.decorate(lruMap,
reverseString);&
&&& String name0
= (String)lazyMap.get("test0");&
&&& String name1
= (String)lazyMap.get("test0");&
&&& String name2
= (String)lazyMap.get("test0");&
&&& String name3
= (String)lazyMap.get("test2");&
&&& String name4
= (String)lazyMap.get("test4");&
&&& String name5
= (String)lazyMap.get("test5");&
&&& String name6
= (String)lazyMap.get("test0");&
&&& String name7
= (String)lazyMap.get("test6");&
&&& String name8
= (String)lazyMap.get("test8");&
&&& String name9
= (String)lazyMap.get("test5");&
&&& Iterator it
= lazyMap.entrySet().iterator();&
while(it.hasNext()){&
Map.Entry entry = (Map.Entry)it.next();&
System.out.println(entry.getValue());&
当然可以在Transformer里可以做任何事,比如从网站爬取数据,并转换成相应的对象等。
如下代码从pchome的ip地址库中查询IP地址,首先定义一个ArticleTransformer对象,每次根据传入的参数从一个URL查询数据并返回。
public class ArticleTransformer implements Transformer
&&& protected
final static int BUF_SIZE = 300;&
&&& protected
String queryURL;&
&&& public
String getQueryURL(){return queryURL;}&
&&& public void
setQueryURL(String queryURL){this.queryURL =
queryURL;}&
&&& protected
long timeO&
&&& public long
getTimeOut(){return timeO}&
&&& public void
setTimeOut(long timeOut){this.timeOut =
&&& public
Object transform(Object obj){&
ArticleRetriever retriever = new
ArticleRetriever((String)obj);&
&&&&&&&&&&&
Thread thread = new Thread(retriever);&
&&&&&&&&&&&
thread.start();&
&&&&&&&&&&&
thread.join(timeOut);&
&&&&&&&&&&&
//Thread.sleep(3*1000);&
}catch(InterruptedException e){&
&&&&&&&&&&&
System.out.println("url request time
return retriever.getResponse();&
&&& public class
ArticleRetriever implements Runnable{&
private S&
private S&
public ArticleRetriever(String name){&
&&&&&&&&&&&
this.name =&
public String getResponse(){&
&&&&&&&&&&&
return this.&
public void run(){&
&&&&&&&&&&&
HttpURL url =&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
HttpClient client = new HttpClient();&
&&&&&&&&&&&&&&&
url = new HttpURL(queryURL+name);&
&&&&&&&&&&&&&&&
GetMethod getMethod = new
GetMethod(url.toString());&
&&&&&&&&&&&&&&&
getMethod.getParams().setContentCharset("UTF-8");&
&&&&&&&&&&&&&&&
client.executeMethod(getMethod);&
&&&&&&&&&&&&&&&
response =
getMethod.getResponseBodyAsString();&
&&&&&&&&&&&
}catch(Exception e){&
&&&&&&&&&&&&&&&
System.out.println("Error get Article& " +
&&&&&&&&&&&
然后如下代码调用
String queryURL =
"http://whois.pconline.com.cn/ip.jsp?ip=";&
ArticleTransformer transformer = new
ArticleTransformer();&
transformer.setQueryURL(queryURL);&
transformer.setTimeOut(500);&
&&& Map lruMap =
new LRUMap(3);&
&&& articleMap =
LazyMap.decorate(lruMap, transformer);&
&&& String ip1 =
(String)articleMap.get("127.0.0.1");&
&&& String ip2 =
(String)articleMap.get("121.0.29.241");&
&&& String ip3 =
(String)articleMap.get("10.25.145.123");&
&&& String ip4 =
(String)articleMap.get("10.121.20.35");&
&&& String ip5 =
(String)articleMap.get("121.230.145.60");&
&&& String ip6 =
(String)articleMap.get("27.186.214.221");&
&&& String ip7 =
(String)articleMap.get("127.0.0.1");&
Writer writer = new
FileWriter("D://hello.txt");&
Iterator it =
articleMap.entrySet().iterator();&
while (it.hasNext()) {&
&&&&&&&&&&&
Map.Entry entry = (Map.Entry)
it.next();&
&&&&&&&&&&&
System.out.println(entry.getValue());&
&&&&&&&&&&&
if(entry.getValue() == null){&
&&&&&&&&&&&&&&&
writer.write("nulln");&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
writer.write((String)entry.getValue());&
&&&&&&&&&&&
if(writer!=null) writer.close();&
&&& } catch
(IOException e) {&
System.out.println("Error write file");&
最后输出如下的结果:
江苏省泰州市(泰兴)电信&
河北省保定市电信&
Internet保留地址
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Java实现一个简单的缓存 - 简书
Java实现一个简单的缓存
阅读原文请访问我的博客
缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。
创建缓存对象EntityCache.java
public class EntityCache {
* 保存的数据
* 设置数据失效时间,为0表示永不失效
long timeO
* 最后刷新时间
long lastRefeshT
public EntityCache(Object datas, long timeOut, long lastRefeshTime) {
this.datas =
this.timeOut = timeO
this.lastRefeshTime = lastRefeshT
public Object getDatas() {
public void setDatas(Object datas) {
this.datas =
public long getTimeOut() {
return timeO
public void setTimeOut(long timeOut) {
this.timeOut = timeO
public long getLastRefeshTime() {
return lastRefeshT
public void setLastRefeshTime(long lastRefeshTime) {
this.lastRefeshTime = lastRefeshT
定义缓存操作接口,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
EntityCache getCacheByKey(String key);
* 获取对应缓存
* @param key
Object getCacheDataByKey(String key);
* 获取所有缓存
* @param key
Map&String, EntityCache& getCacheAll();
* 判断是否在缓存中
* @param key
boolean isContains(String key);
* 清除所有缓存
void clearAll();
* 清除对应缓存
* @param key
void clearByKey(String key);
* 缓存是否超时失效
* @param key
boolean isTimeOut(String key);
* 获取所有key
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
public EntityCache getCacheByKey(String key) {
if (this.isContains(key)) {
return caches.get(key);
* 获取对应缓存
* @param key
public Object getCacheDataByKey(String key) {
if (this.isContains(key)) {
return caches.get(key).getDatas();
* 获取所有缓存
* @param key
public Map&String, EntityCache& getCacheAll() {
* 判断是否在缓存中
* @param key
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
public boolean isTimeOut(String key) {
if (!caches.containsKey(key)) {
EntityCache cache = caches.get(key);
long timeOut = cache.getTimeOut();
long lastRefreshTime = cache.getLastRefeshTime();
if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime &= timeOut) {
* 获取所有key
public Set&String&
getAllKeys() {
return caches.keySet();
CacheListener.java,监听失效数据并移除。
public class CacheListener{
Logger logger = Logger.getLogger("cacheLog");
private CacheManagerImpl cacheManagerI
public CacheListener(CacheManagerImpl cacheManagerImpl) {
this.cacheManagerImpl = cacheManagerI
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");
* 测试缓存和缓存失效
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());
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
logger.info("test:" + cacheManagerImpl.getCacheByKey("test"));
logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest"));
* 测试线程安全
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);
//因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来
synchronized (cacheManagerImpl) {
int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1;
cacheManagerImpl.putCache(key,value , 0);
exec.shutdown();
exec.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e1) {
e1.printStackTrace();
logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());
testCacheManager()输出结果如下:
10:33:51 io.github.brightloong.cache.TestCache testCacheManager
信息: test:test
10:33:51 io.github.brightloong.cache.TestCache testCacheManager
信息: myTest:myTest
10:34:01 io.github.brightloong.cache.CacheListener$1 run
信息: test缓存被清除
10:34:06 io.github.brightloong.cache.CacheListener$1 run
信息: myTest缓存被清除
10:34:11 io.github.brightloong.cache.TestCache testCacheManager
信息: test:null
10:34:11 io.github.brightloong.cache.TestCache testCacheManager
信息: myTest:null
testThredSafe()输出结果如下(选出了各种结果中的一个举例):
10:35:36 io.github.brightloong.cache.TestCache testThredSafe
可以看到并不是预期的结果100,为什么呢?ConcurrentHashMap只能保证单次操作的原子性,但是当复合使用的时候,没办法保证复合操作的原子性,以下代码:
if (!cacheManagerImpl.isContains(key)) {
cacheManagerImpl.putCache(key, 1, 0);
多线程的时候回重复更新value,设置为1,所以出现结果不是预期的100。所以办法就是在CacheManagerImpl.java中都加上synchronized,但是这样一来相当于操作都是串行,使用ConcurrentHashMap也没有什么意义,不过只是简单的缓存还是可以的。或者对测试方法中的run里面加上synchronized块也行,都是大同小异。更高效的方法我暂时也想不出来,希望大家能多多指教。
Remember what should be remembered, and forget what should be forgotten.Alter what is changeable, and accept what is mutable.
Java 基础思维导图,让 Java 不再难懂 - 工具资源 - 掘金思维导图的好处 最近看了一些文章的思维导图,发现思维导图真是个强大的工具。了解了思维导图的作用之后,觉得把它运用到java上应该是个不错的想法,这样回顾知识点的时候一目了然,快速知道自己的短板。 思维导图...
一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 publicclassUnsafeLazyInitiallization{ privatestaticUnsafeLazyIni privateUn...
从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗offer。我找的是java后台开发,把常见的问题分享给大家,有一些是自己的总结,有一些是网上借鉴的内容。希望能帮助到各位。预祝各位同学拿到自己心仪的offer...
Java8张图 11、字符串不变性
12、equals()方法、hashCode()方法的区别
13、Java异常类的层次结构
14、集合类的层次结构
25、Java同步
37、堆和栈
38、Java虚拟机运行时数据区域
1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io的语法,虚拟机方面的语法。 1、一个&.java&源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个publ...
独立思考 在生活中,想必你或多或少也有过这样的经历:跟同学、朋友或者同事外出一起吃饭的时候,当你让ta们点菜时,ta们之中总会有人给你的回答是“随便”,永远不会给你一个明确的意见。每当这个时候,你是不是会感觉特别无语,你总会担心自己点的与ta说的“随便”不符。 其实,我们自...
6月23日,由昌邑市委宣传部主办、中央电视台农业频道、龙池镇委镇政府承办的“昌邑市第二届乡村旅游节暨第二届龙乡文化节”开幕式在梦幻花海农业生态观光园盛大举行。 龙池镇位于山东省潍坊市东北部,北临渤海,东临青岛,西接潍坊,地理位置优越。龙池镇拥有6公里海岸线和27万公亩盐田,...
壹. 2016年年尾,我的一个朋友婚姻出了问题,剧情的跌岩起伏超过了电影电视剧,在一次5个女人的撸串聚会上,其他四个人哭成了狗,喝成了鬼,我刚拔了智齿,没吃没喝没哭,那一晚我用一个人的清醒撑起了她们四个人的天。 “我可能要离婚了”!她说。 “你别闹!”我说。 “我觉得我们已...
宛风|第43个故事|心情涂鸦 红的 绿的 黄的 蓝的 紫的 黑的 白的 各种颜色都是心情的糖果 音乐响起 心情开始涂鸦 随便画呀 随便写呀 加点颜色 心情变亮了 释放双手 让它自由 释放心情 让心自由 来吧,我们一起涂鸦 我是宛风。活好自己,温暖如初 第25天之前只是听说过缓存池,也没有具体的接触到,今天做项目忽然想到了用缓存池,就花了一上午的时间研究了下缓存池的原理,并实现了基本的缓存池功能。
* @author xiaoquan
* @create 日 上午10:32:13
public class CachePool {
private static CacheP//缓存池唯一实例
private static Map&String,Object& cacheI//缓存Map
private CachePool(){
cacheItems = new HashMap&String,Object&();
* 得到唯一实例
public synchronized static CachePool getInstance(){
if(instance == null){
instance = new CachePool();
* 清除所有Item缓存
public synchronized void clearAllItems(){
cacheItems.clear();
* 获取缓存实体
* @param name
public synchronized Object getCacheItem(String name){
if(!cacheItems.containsKey(name)){
CacheItem cacheItem = (CacheItem) cacheItems.get(name);
if(cacheItem.isExpired()){
return cacheItem.getEntity();
* 存放缓存信息
* @param name
* @param obj
* @param expires
public synchronized void putCacheItem(String name,Object obj,long expires){
if(!cacheItems.containsKey(name)){
cacheItems.put(name, new CacheItem(obj, expires));
CacheItem cacheItem = (CacheItem) cacheItems.get(name);
cacheItem.setCreateTime(new Date());
cacheItem.setEntity(obj);
cacheItem.setExpireTime(expires);
public synchronized void putCacheItem(String name,Object obj){
putCacheItem(name,obj,-1);
* 移除缓存数据
* @param name
public synchronized void removeCacheItem(String name){
if(!cacheItems.containsKey(name)){
cacheItems.remove(name);
* 获取缓存数据的数量
public int getSize(){
return cacheItems.size();
public class CacheItem {
private Date createTime = new Date();//创建缓存的时间
private long expireTime = 1;//缓存期满的时间
private O//缓存的实体
public CacheItem(Object obj,long expires){
this.entity =
this.expireTime =
public boolean isExpired(){
return (expireTime != -1 && new Date().getTime()-createTime.getTime() & expireTime);
* 省略getter、setter方法
阅读(...) 评论()18:02 提问
java map 多线程遍历把key,value 插入缓存数据库
这是一个map 里面大概有10万数据,在这里我想改成多线程遍历map插入缓存数据库。
不知道怎么写。求大神赐教。
按赞数排序
因为想到map get操作是不加锁的。所以不知道怎么保证一个key,value 插入一次。
你看这样行不行
public class MapTest {
public static void main(String[] args) {
Map&String, String& map = new HashMap&String, String&();
for(int i = 0; i & 400; i++){
map.put(String.valueOf(i), null);
Runnable runnable = new MyRunnable(map.entrySet().iterator());
Thread t1 = new Thread(runnable);
t1.setName("Thread1");
Thread t2 = new Thread(runnable);
t2.setName("Thread2");
Thread t3 = new Thread(runnable);
t3.setName("Thread3");
t1.start();
t2.start();
t3.start();
class MyRunnable implements Runnable {
private Iterator&Map.Entry&String, String&& set =
private Object lock = new Object();
public MyRunnable(Iterator&Map.Entry&String, String&& set) {
this.set =
public void run() {
synchronized (lock) {
while (set.hasNext()) {
lock.notifyAll();
System.out.println(Thread.currentThread().getName() + "读取到Key "
+ set.next().getKey());
Thread.sleep(1000);
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
lock.notifyAll();
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐使用Map实现java缓存,但是如何从缓存中获取数据呢,我一直取值是空的
[问题点数:60分,结帖人u]
本版专家分:0
结帖率 100%
CSDN今日推荐
本版专家分:3585
2016年10月 Java大版内专家分月排行榜第二
2016年9月 Java大版内专家分月排行榜第三
本版专家分:0
结帖率 100%
本版专家分:325
本版专家分:0
结帖率 100%
本版专家分:15049
2016年6月 Java大版内专家分月排行榜第一2016年5月 Java大版内专家分月排行榜第一2016年4月 Java大版内专家分月排行榜第一
2017年2月 Java大版内专家分月排行榜第二2017年1月 Java大版内专家分月排行榜第二2016年7月 Java大版内专家分月排行榜第二
2016年12月 Java大版内专家分月排行榜第三2016年10月 Java大版内专家分月排行榜第三2016年8月 Java大版内专家分月排行榜第三
本版专家分:7961
2016年12月 Java大版内专家分月排行榜第一2016年9月 扩充话题大版内专家分月排行榜第一2016年5月 扩充话题大版内专家分月排行榜第一
2016年7月 扩充话题大版内专家分月排行榜第二
2017年1月 Java大版内专家分月排行榜第三2016年12月 扩充话题大版内专家分月排行榜第三2016年10月 扩充话题大版内专家分月排行榜第三2016年6月 扩充话题大版内专家分月排行榜第三
本版专家分:0
结帖率 100%
匿名用户不能发表回复!|
CSDN今日推荐

我要回帖

更多关于 java 获取缓存数据 的文章

 

随机推荐