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{
}
}
}
复制代码