java缓存系统
第一版
package cache;
import java.util.HashMap;
import java.util.Map;
public class Cache1 {
private Map<String, Object> map=new HashMap<String, Object>();
private static Cache1 cache1=new Cache1();
private Cache1(){
}
public static Cache1 getInstanceCache1(){
return cache1;
}
public void setObject(String key,Object value){
map.put(key, value);
}
public Object getObject(String key){
Object value=null;
value=map.get(key);
if (value==null) {
value=getFromDB(key); // 从远程数据库获得
map.put(key, value);
}
return value;
}
/**
*仅仅只是模拟
*/
private Object getFromDB(String key) {
return null;
}
}
所谓的缓存,就是把经常用的数据存储到内存中,下次用的时候能很快的拿到。因而,上面的核心代码其实就是getObject。但是,得承认,上面的代码实在是太过简陋了。上面的测试程序很简单我就不写了。
第二版
之前第一版的缓存只是个实例代码,还算不上工具,因为它并没有对某一个"计算"操作做包装。我知道我说的很模糊,咱们看代码。
package cache;
public interface GetResutl {
public Object get(Object o);
}
package cache;
public class ComputeSum implements GetResutl {
@Override
public Object get(Object o) {
if ( !(o instanceof Integer) ){
throw new IllegalArgumentException (o+"is not Integer");
}
int n=(int) o;
int result=0;
for (int i = 1; i <= n; i++) {
result+=i;
}
return result;
}
}
package cache;
public class ComputeMultiply implements GetResutl {
@Override
public Object get(Object o) {
if ( !(o instanceof Integer) ){
throw new IllegalArgumentException (o+"is not Integer");
}
int n=(int) o;
int result=1;
for (int i = 1; i <= n; i++) {
result*=i;
}
return result;
}
}
第一版的缓存系统,不能缓存某种操作的结果。
看了上面的连加,与连乘。
我们就大概知道新的缓存该是个什么样了。
package cache;
import java.util.HashMap;
import java.util.Map;
public class Cache2 {
private Map<String, Object> map=new HashMap<String, Object>();
private GetResutl getResutl=null;
public Cache2(GetResutl r){
this.getResutl=r;
}
public void setObject(String key,Object value){
map.put(key, value);
}
public Object getObject(String key){
Object value=null;
value=map.get(key);
if (value==null) {
value=getResutl.get(key);
map.put(key, value);
}
return value;
}
}
另外多嘴一句,Cahe2中有一个接口GetResut,之后再调用GetResult的某一个方法,这种设计似乎叫做策略模式。
第三版
如果ComputeMultiply中的get方法的运行需要花很长时间,同时我们也不着急要它计算的结果,第二版的计算是放在一个线程里的,这样效率不高。
我们试试CallAble。
package cache;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ComputeSum implements GetResutl {
@Override
public Object get(Object o) {
final Long n=Long.valueOf((String) o);
Callable<Long> c=new Callable<Long>() {
@Override
public Long call(){
Long result=0L;
for (int i = 1; i <= n; i++) {
result+=i;
}
return result;
}
};
return new FutureTask<>(c);
}
}
连乘的写法与之类似,不再赘述。
再看cache的写法。
</pre><pre name="code" class="java">package cache;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
public class Cache3 {
private Map<String, FutureTask<Object>> map=new HashMap<String, FutureTask<Object> >();
private GetResutl getResutl=null;
public Cache3(GetResutl r){
this.getResutl=r;
}
@SuppressWarnings("unchecked")
public Object getObject(String key){
FutureTask<Object> value=null;
FutureTask<Object> ft=map.get(key);
if (ft==null) {
value= (FutureTask<Object>) getResutl.get(key);
map.put(key, value);
ft=value;
}
ft.run();
Object result=null;
try {
result = ft.get();
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
我们看看版本三的测试代码
public static void main(String[] args) {
GetResutl getResutl=new ComputeSum();
Cache3 c3=new Cache3(getResutl);
long t1=0;
long t2=0;
t1=System.currentTimeMillis();
System.out.println(c3.getObject(""+1234566));
t2=System.currentTimeMillis();
System.out.println(t2-t1 );
t1=System.currentTimeMillis();
System.out.println(c3.getObject(""+1234566));
t2=System.currentTimeMillis();
System.out.println(t2-t1 );
t1=System.currentTimeMillis();
System.out.println(c3.getObject(""+1234567));
t2=System.currentTimeMillis();
System.out.println(t2-t1 );
t1=System.currentTimeMillis();
System.out.println(c3.getObject(""+1234567));
t2=System.currentTimeMillis();
System.out.println(t2-t1 );
t1=System.currentTimeMillis();
System.out.println(c3.getObject(""+1234567));
t2=System.currentTimeMillis();
System.out.println(t2-t1 );
}
输出:
762077221461
16
762077221461
0
762078456028
15
762078456028
0
762078456028
0
第四版
java并发编程中提到的一个例子。
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
interface Computable<K,V>{
V compute(final K arg);
}
/**
* 实现简单缓存系统
* @author mzy
*
* @param <K> key
* @param <V> value
*/
public class FutureCache<K,V> implements Computable<K,V>{
private final ConcurrentHashMap<K, Future<V>> cache = new ConcurrentHashMap<K ,Future<V>>();
private final Computable<K, V> c;
public FutureCache(Computable<K, V> c) {
this.c = c;
}
@Override
public V compute(final K key) {
while(true){
Future<V> future = cache.get(key);
if(future == null){
Callable<V> eval = new Callable<V>() {
@Override
public V call() throws Exception { return c.compute(key); }
};
FutureTask<V> ftask = new FutureTask<V>(eval);
//使用putIfAbsent原子操作避免有上面if(future == null)引起的相同值的缺陷
future = cache.putIfAbsent(key, ftask);
if(future == null) { future = ftask; ftask.run(); }
}
try {
return future.get();
} catch (InterruptedException e) {
//出现中断异常应该从 cache中移除Future,防止缓存污染
cache.remove(key,future);
} catch (ExecutionException e) {
//执行中的异常应当抛出,获得恰当处理
throw new RuntimeException(e.getCause());
}
}
}
}
测试程序:
public class Test {
public static void main(String[] args) {
final Computable<Integer, Integer> c = new Computable<Integer, Integer>() {
@Override
public Integer compute(Integer arg) {
Integer sum = 0;
for(Integer i=0;i<arg;i++){
sum+=i;
}
return sum;
}
};
final Computable<Integer, Integer> cache = new FutureCache<Integer,Integer>(c);
long start = System.currentTimeMillis();
cache.compute(10000);
long stop = System.currentTimeMillis();
System.out.println(stop-start);
start = System.currentTimeMillis();
cache.compute(10000);
stop = System.currentTimeMillis();
System.out.println(stop-start);
start = System.currentTimeMillis();
cache.compute(10000);
stop = System.currentTimeMillis();
System.out.println(stop-start);
start = System.currentTimeMillis();
cache.compute(10000);
stop = System.currentTimeMillis();
System.out.println(stop-start);
}
}
参考资料
http://my.oschina.net/ccdvote/blog/131876?p=1
java缓存系统的更多相关文章
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- 缓存系统MemCached的Java客户端优化历程
Memcached 是什么? Memcached是一种集中式Cache,支持分布式横向扩展.这里需要解释说明一下,很多开发者觉得Memcached是一种分布式缓存系统,但是其实Memcached服务端 ...
- Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- JAVA 并发编程-读写锁之模拟缓存系统(十一)
在多线程中,为了提高效率有些共享资源同意同一时候进行多个读的操作,但仅仅同意一个写的操作,比方一个文件,仅仅要其内容不变能够让多个线程同一时候读,不必做排他的锁定,排他的锁定仅仅有在写的时候须要,以保 ...
- [Java 缓存] Java Cache之 DCache的简单应用.
前言 上次总结了下本地缓存Guava Cache的简单应用, 这次来继续说下项目中使用的DCache的简单使用. 这里分为几部分进行总结, 1)DCache介绍; 2)DCache配置及使用; 3)使 ...
- Memcache缓存系统构建一
在如今这个高效率的社会中,怎样将这个高效率应用到自己的程序中,是一个值得追寻和值得探讨的问题.因为这个memcache能够很好的提高检索速度,提升用户体验,而且重要的是减少数据库的访问.这就大大的提高 ...
- 深入探讨在集群环境中使用 EhCache 缓存系统
EhCache 缓存系统简介 EhCache 是一个纯 Java 的进程内缓存框架,具有快速.精干等特点,是 Hibernate 中默认的 CacheProvider. 下图是 EhCache 在应用 ...
- (转)java缓存技术,记录
http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇 ...
- JAVA缓存技术
介绍 JNotify:http://jnotify.sourceforge.net/,通过JNI技术,让Java代码可以实时的监控制定文件夹内文件的变动信息,支持Linux/Windows/MacOS ...
随机推荐
- 用Netty开发中间件:网络编程基础
用Netty开发中间件:网络编程基础 <Netty权威指南>在网上的评价不是很高,尤其是第一版,第二版能稍好些?入手后快速翻看了大半本,不免还是想对<Netty权威指南(第二版)&g ...
- DB查询分析器7.01新增的周、月SQL执行计划功能
DB查询分析器7.01新增的周.月SQL执行计划功能 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 1 引言 中国本土 ...
- 【Unity3D】 Unity Chan项目分享
写在前面 之前的一个博文里分享了日本Unity酱的项目,如果大家有去仔细搜Unity酱的话,就会发现日本Unity官方还放出了一个更完整的Unity酱的项目,感觉被萌化了!(事实上,Unity日本经常 ...
- 手把手图文教你从Eclipse项目迁移Android Studio
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52937391 从Android的 ...
- Android自动打包工具aapt详解
概念 在Android.mk中有LOCAL_AAPT_FLAGS配置项,在gradle中也有aaptOptions,那么aapt到底是干什么的呢? aapt即Android Asset Packagi ...
- ROS探索总结(十七)——构建完整的机器人应用系统
上一篇博客介绍了HRMRP机器人平台的设计,基于该平台,可以完成丰富的机器人应用,以较为典型的机器人导航为例,如何使用HRMRP来完成相应的功能?本篇博客将详细介绍如何将HRMRP应用到 ...
- Scala actor的使用
Actor 为什么需要Actor? Actor的本质即万物皆Actor, Actor之间只有发送消息这一种通信方式.例如,无论是管理员让工作者干活,还是工作者把成果交还给管理员,它们之间也要通过发送消 ...
- Team Foundation Server 2015 Update 2.1 发布日志
微软在 2016年5月5日发布了Visual Studio Team Foundation Server 2015 update 2.1. 下面我们来看看Update2.1中给我们带来了哪些新功能. ...
- Retrofit2.0 ,OkHttp3完美同步持久Cookie实现免登录(二)
原文出自csdn: http://blog.csdn.net/sk719887916/article/details/51700659: 通过对Retrofit2.0的<Retrofit 2.0 ...
- FFmpeg的H.264解码器源代码简单分析:解码器主干部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...