Java緩存主要分爲三種:java
一、FIFOsql
二、LRU數據庫
三、LFUapache
它們通常應用於瀏覽器中,使不少操做更加方便快捷。瀏覽器
一、FIFO:緩存
FIFO是按存入的順序進行排序的,若是命中緩存中的任意一個數據,也不會破壞先進先出的規則。若是新增了一個緩存以外的數據,會把最早存入的數據移除。 先入先出,就和隊列同樣,先進隊列的先出隊列。bash
import java.util.LinkedHashMap;
public class FIFOCache<K,V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 436014030358073695L;
private final int SIZE;
public FIFOCache(int size) {
super();
SIZE = size;
}
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > SIZE;
}
}
public class FIFOCacheTest {
public static void main(String[] args) {
FIFOCache<Integer, Integer> map = new FIFOCache<Integer, Integer>(10);
for (int i = 0; i++ < 10;) {
map.put(i, i);
}
System.out.println("起始存儲狀況:"+map.toString());
map.put(8, 8);
System.out.println("命中一個已存在的數據:"+map.toString());
map.put(11, 11);
System.out.println("新增一個數據後:"+map.toString());
}
}
複製代碼
二、LRU: 當某一個數據被訪問命中就會按照LRU規則放到隊列最前面。若是新增一個不存在緩存的數據,會把該數據放到最前面,同時移除最先訪問過的數據。session
import java.util.LinkedHashMap;
public class LRUCache<K,V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 5853563362972200456L;
private final int SIZE;
public LRUCache(int size) {
super(size, 0.75f, true);
SIZE = size;
}
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
return size() > SIZE;
}
}
public class LRUCacheTest {
public static void main(String[] args) {
LRUCache<Integer, Integer> map = new LRUCache<Integer, Integer>(10);
for (int i = 0; i++ < 10; ) {
map.put(i, i);
}
System.out.println("起始存儲狀況:"+map.toString());
map.get(7);
System.out.println("命中一個已存在的數據:"+map.toString());
map.put(8, 8+1);
System.out.println("覆蓋一個已存在的數據:"+map.toString());
map.put(11, 11);
System.out.println("新增一個數據後:"+map.toString());
}
}
複製代碼
三、LFU: 對存儲的數據都會有一個計數引用,而後隊列按數據引用次數排序,引用數多的排在最前面,引用數少的排在後面。若是這個時候有新的數據進來,把最後面的數據刪除,把新進數據排在最後面,且引用次數爲1mybatis
import java.util.*;
public class LFUCache{
static class Value implements Comparable<Value>{
Object key;
Object val;
int hitCount;
public Value(Object v, Object key) {
this.key = key;
this.val = v;
this.hitCount = 1;
}
public void setVal(Object obj){
this.val = obj;
}
public void countInc(){
hitCount++;
}
@Override
public int compareTo(Value o) {
if(o instanceof Value){
Value v = (Value) o;
if(this.hitCount > v.hitCount)
return 1;
else
return -1;
}
return 0;
}
}
final int SIZE;
private Map<Object, Value> map = new HashMap<Object, Value>();
public LFUCache(int size) {
SIZE = size;
}
public Object get(Object k){
if(k == null)
return null;
map.get(k).countInc();
return map.get(k).val;
}
public void put(Object k, Object v){
if(map.get(k) != null){
map.get(k).countInc();
map.get(k).setVal(v);
}else{
if(map.size() >= SIZE){
remove();
}
Value value = new Value(v, k);
map.put(k, value);
}
}
public void remove(){
Value v = Collections.min(map.values());
map.remove(v.key);
}
public String showList(){
List<Value> list = new ArrayList<Value>();
list.addAll(map.values());
Collections.sort(list);
String result = "";
for (Value value : list) {
result +=value.key+"="+value.val+" ";
}
return result;
}
}
public class LFUCacheTest {
public static void main(String[] args) {
LFUCache map = new LFUCache(10);
for (int i = 0; i++ < 10; ) {
map.put(i, i);
}
System.out.println("起始存儲狀況:"+map.showList());
map.get(7);
System.out.println("命中一個已存在的數據:"+map.showList());
map.put(8, 8+1);
System.out.println("覆蓋一個已存在的數據:"+map.showList());
map.put(11, 11);
System.out.println("新增一個數據後:"+map.showList());
map.put(5, 5);
map.put(5, 5);
map.put(6, 6);
map.put(6, 6);
map.put(6, 6);
System.out.println("修改命中次數後:"+map.showList());
}
}
複製代碼
mybatis的緩存能夠分爲一級和二級緩存。app
其中一級緩存也叫本地緩存;當你要在一段時間內獲取相同的數據時,若是每次都去查詢數據庫,就會顯得特別麻煩,這時候一級緩存就派上了用場,它可以將與數據庫會話時查詢到的數據放在本地的緩存中,這時候要相同數據就能夠直接從緩存中獲取,就省去不少麻煩。
二級緩存也叫做全局緩存。一個命名域對應一個二級緩存,發生一個會話的時候查詢數據中的數據,這個數據就會被保留在當前的一級緩存中。當會話關閉的時候一級緩存的數據就會被保存在二級緩存中;開始新會話的時候,若是要查詢新的信息就能夠用二級緩存中的內容。
//截取的一部分實現代碼
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import com.atguigu.mybatis.bean.Department;
import com.atguigu.mybatis.bean.Employee;
import com.atguigu.mybatis.dao.DepartmentMapper;
import com.atguigu.mybatis.dao.EmployeeMapper;
import com.atguigu.mybatis.dao.EmployeeMapperAnnotation;
import com.atguigu.mybatis.dao.EmployeeMapperDynamicSQL;
import com.atguigu.mybatis.dao.EmployeeMapperPlus;
public class MyBatisTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFirstLevelCache() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
}finally{
openSession.close();
}
}
@Test
public void testSecondLevelCache() throws IOException{
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
SqlSession openSession2 = sqlSessionFactory.openSession();
try{
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
Employee emp01 = mapper.getEmpById(1);
System.out.println(emp01);
openSession.close();
Employee emp02 = mapper2.getEmpById(1);//從二級緩存中拿的數據
System.out.println(emp02);
openSession2.close();
}finally{
}
}
}
複製代碼