本文从线程不安全、线程安全、高性能三个方面一步步优化缓存模型,如果有疑问或者写的不好的地方可以留言沟通
1. 缓存模型(线程不安全)
import java.util.HashMap;
import java.util.Map;
public class CacheDemo {
//声明一个map,用来作为缓存模型
private static Map<String, Object> map = new HashMap<String, Object>();
public static Object getValue(String key) {
Object value = map.get(key);
if (value == null) {
value = "abc";//这里是去数据库查询
map.put(key, value);//将数据放到缓存模型中
}
return value;
}
}
从上面的代码可以看出,当10个线程同时访问的时候,会出现到数据查询次数也是10次,这样数据库访问压力大,不推荐使用
2. 缓存模型(线程安全)
import java.util.HashMap;
import java.util.Map;
public class CacheDemo {
//声明一个map,用来作为缓存模型
private static Map<String, Object> map = new HashMap<String, Object>();
public synchronized static Object getValue(String key) {
Object value = map.get(key);
if (value == null) {
value = "abc";//这里是去数据库查询
map.put(key, value);//将数据放到缓存模型中
}
return value;
}
}
在getValue方法上加上后,10个线程同时访问的话,减少了数据库访问压力,但是出现一个情况,就是线程之间要通过排队抢锁才能进行访问
3. 缓存模型(高性能)
3.1 通过synchronized设计
import java.util.HashMap;
import java.util.Map;
public class CacheDemo {
//声明一个map,用来作为缓存模型
private static Map<String, Object> map = new HashMap<String, Object>();
public static Object getValue(String key) {
Object value = map.get(key);
if(value==null){
synchronized (CacheDemo.class){
if(value==null){
value="abc";//这里是去数据库查询
map.put(key,value);//将数据放到缓存模型中
}
}
}
return value;
}
}
从上面的代码设计可以看出,如果10个线程访问的数据已经存在于map中,不会出现竞争锁的情况,直接返回value,如果访问的数据不存在于map中,才会竞争锁进行数据库查询,并且只有第一个抢到锁的线程查询数据库,其他的线程拿到锁以后,发现value已经不为null了
3.2 通过ReadWriteLock设计
下面这个用的读写锁,设计思想和上面synchronized是一样的
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class CacheDemo {
//声明一个map,用来作为缓存模型
private static Map<String, Object> map = new HashMap<String, Object>();
//声明一个读写锁
private static ReadWriteLock rwl = new ReentrantReadWriteLock();
public static Object getValue(String key) {
Object value = null;
try {
rwl.readLock().lock();//开启读锁
value = map.get(key);
if (value == null) {
try {
rwl.readLock().unlock();//关闭读锁
rwl.writeLock().lock();//开启写锁
if (value == null) {
value = "abc";//这里是去数据库查询
map.put(key, value);//将数据放到缓存模型中
}
}catch (Exception e){
e.printStackTrace();
}
finally {
rwl.writeLock().unlock();//关闭写锁
rwl.readLock().lock();//开启读锁
}
}
}catch (Exception e){
e.printStackTrace();
}
finally {
rwl.readLock().unlock();//关闭读锁
}
return value;
}
}