您的位置:首页 > 编程语言 > Java开发

java缓存系统

2015-08-06 10:44 519 查看

第一版

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: