前提:
數據庫表 student:
create table student(
id int,
name varchar(15)
);
一.線程不安全版本
import java.util.HashMap;
import java.util.Map;
public class CacheDemo {
//map 用來作緩存模型
private static Map<String, Object> map = new HashMap<String, Object>();
//根據 key 的值,返回其對應的 value
public static Object getValue(String key) {
Object value = map.get(key);
if (value == null) {
int ID=Integer.value(key);
value =//去數據庫查詢該 key 對應的 value ( select name from student where id=ID;)
map.put(key, value); //將數據放到緩存模型中
}
return value; //map 中存在該 key 對應的值那麼則返回
}
}
從上面的代碼可以看出,當有 10 個線程同時訪問數據庫的時候,會出現數據查詢的次數也是10次,這樣對數據庫的訪問壓力過大,不推薦使用。
二.線程安全版本
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 = //去數據庫查詢該 key 對應的 value ( select name from student where id=ID;)
map.put(key, value); //將數據放到緩存模型中
}
return value;
}
}
從上面的代碼可以看出,在 getValue() 方法上加上 synchronized 後,當有 10 個線程(10 個線程攜帶的 key 值都一樣)都要訪問數據庫的時候,線程之間只有搶到了鎖的線程纔可以訪問數據庫進行數據查詢,因此一定程度上減少了數據庫訪問壓力,但是鎖的粒度比較大。
三.升級版本
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"; //去數據庫查詢該 key 對應的 value ( select name from student where id=ID;)
map.put(key,value);//將數據放到緩存模型中
}
}
}
return value;
}
}
從上面的代碼可以看出,如果 10 個線程(10 個線程攜帶的 key 值都一樣)訪問的數據已經存在於 map 中了,那麼就不會出現競爭鎖的情況,直接返回 value 即可。但是如果線程訪問的數據不存在於 map 中的時候,纔會出現競爭鎖的情況然後進行數據庫的查詢,並且只有第一個搶到鎖的線程纔可以查詢數據庫,其他的線程拿到鎖以後,發現 value 已經不爲 null 了,直接返回 value 的值即可。
原文來源:https://blog.csdn.net/u010452388/article/details/82725299