欢迎使用 {小书匠}(xiaoshujiang)编辑器,您可以通过设置里的修改模板来改变新建文章的内容。
1. 利用现有的缓存框架,redis等nosql数据库.
优点: 稳定,适用分布式.数据共享.
缺点: 需要学习成本对新手不友好,较重.
2. 手写的缓存工具
优点: 便于学习,轻量级
缺点: 不适用分布式
package com.word.cache;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 非分布式手写高并发缓存实例
*/
public class Cache {
//键值对集合
private final static Map map = new HashMap<>();
//定时器线程池
private final static ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
/**
*
* 添加缓存
* @param key
* @param data
*/
public synchronized static void put(String key,Object data){
put(key,data,0);
}
/**
* 添加缓存
* @param key 键
* @param data 值
* @param expire 过期时间(ms) 0 表示无限长
*/
public synchronized static void put(String key,Object data,int expire){
//清除原键值对
Cache.remove(key);
//设置过期时间
if (expire > 0 ){
Future future = scheduledExecutorService.schedule(()-> {
//过去清除该缓存数据
synchronized (Cache.class){
map.remove(key);
}
},expire,TimeUnit.MILLISECONDS);
map.put(key,new Entity(data,future));
}else {
//不设置过期时间
map.put(key,new Entity(data,null));
}
}
/**
* 读取缓存
* @param key
* @return
*/
public synchronized static Object get(String key){
Entity entity = map.get(key);
return entity == null? null:entity.getValue();
}
/**
* 读取缓存
* @param key
* @param clazz
* @param
* @return
*/
public synchronized static T get(String key,Class clazz){
return clazz.cast(Cache.get(key));
}
/**
* 清除缓存
* @param key
* @return
*/
public synchronized static Object remove(String key){
//清除原缓存数据
Entity entity = map.remove(key);
if (entity == null) return null;
//清除原键值对定时器
Future future = entity.getFuture();
if (future != null) future.cancel(true);
return entity.getValue();
}
/**
* 查询当前缓存的键值对数量
* @return
*/
public synchronized static int size(){
return map.size();
}
/**
* 缓存实体类
*/
private static class Entity{
//存储的数据
private T value;
//定时器
private Future future;
public Entity(T value, Future future) {
this.value = value;
this.future = future;
}
/**
* 获取数据
* @return
*/
public T getValue() {
return value;
}
/**
* 获取定时器
* @return
*/
public Future getFuture() {
return future;
}
}
}
package com.word.cache;
import java.util.concurrent.*;
/**
* 测试缓存
*/
public class CacheTest {
//自定义线程池
public static ExecutorService executorService = new ThreadPoolExecutor(2,10,0L, TimeUnit.SECONDS,new LinkedBlockingQueue(32),new ThreadPoolExecutor.CallerRunsPolicy());
public static void main(String[] args) throws InterruptedException, ExecutionException {
String key = "id";
//不设置过期时间
System.err.println("***********************不设置过期时间************************");
Cache.put(key,123);
System.out.println("key:"+key+",value:"+Cache.get(key));
System.out.println("key:"+key+",value:"+Cache.get(key));
System.out.println("key:"+key+",value:"+Cache.get("trykill"));
//设置过期时间
System.err.println("***********************设置过期时间************************");
Cache.put(key,"123456",1000);
System.out.println("key:"+key+",value:"+Cache.get(key));
Thread.sleep(2000);
System.out.println("key:"+key+",value:"+Cache.get(key));
/*####################################高并发测试#######################################*/
Future[] futures = new Future[100];
/**put***/
long start = System.currentTimeMillis();
for (int i = 0; i<100;i++){
futures[i] = executorService.submit(()->{
long start1 = System.currentTimeMillis();
for (int j = 0;j<100000;j++){
Cache.put(Thread.currentThread().getName()+j,j);
}
System.err.println("&&&&&&:"+Thread.currentThread().getName()+",添加耗时:"+(System.currentTimeMillis() - start1));
});
}
//等待执行完毕打印持续时间
for (Future future : futures){
future.get();
}
System.err.println("添加耗时:"+(System.currentTimeMillis() - start));
/**get***/
long startGet = System.currentTimeMillis();
for (int i = 0; i < 100;i++){
futures[i] = executorService.submit(()->{
for (int j = 0;j<100000;j++){
Cache.get(Thread.currentThread().getName()+j);
}
});
}
//等待执行完毕打印持续时间
for (Future future : futures){
future.get();
}
System.err.println("查询耗时:"+(System.currentTimeMillis() - startGet));
System.err.println("缓存容量:"+Cache.size());
}
}
***********************不设置过期时间************************
key:id,value:123
key:id,value:123
key:id,value:null
***********************设置过期时间************************
key:id,value:123456
key:id,value:null
&&&&&&:pool-1-thread-1,添加耗时:465
&&&&&&:pool-1-thread-4,添加耗时:470
&&&&&&:pool-1-thread-7,添加耗时:479
&&&&&&:pool-1-thread-5,添加耗时:485
&&&&&&:pool-1-thread-10,添加耗时:504
&&&&&&:pool-1-thread-6,添加耗时:537
&&&&&&:main,添加耗时:1357
...省略...
&&&&&&:pool-1-thread-2,添加耗时:170
添加耗时:4112
查询耗时:1957
缓存容量:1100000