本地緩存系統簡易設計

本地Cache系統簡易設計

爲何使用緩存?

  • 下降數據庫的訪問壓力。
  • 提升查詢效率。
  • 改善用戶體驗。

你都瞭解哪些緩存?

  • 數據庫內置緩存(DBA修改)。
  • 數據層緩存(由持久層框架決定,例如mybatis)
  • 業務層緩存(由業務層框架以及第三緩存產品決定:本地緩存+分佈式緩存)
  • 瀏覽器緩存(Cache-Control)

設計緩存都應該考慮什麼問題?

  • 存儲結構:使用什麼結構存儲數據?(數組,鏈表,散列存儲-哈希存儲)
  • 淘汰算法:有限容量(LRU,FIFO,.....),不限容量(GC)
  • 併發安全:保證線程安全。
  • 任務調度:每隔多長時間清理一下緩存。
  • 日誌記錄:是否命中?(命中率)

緩存系統設計基礎

緩存標準定義

package com.cy.java.cache;  
/\*\* Cache接口設計\*/  
public interface Cache {  
 public void putObject(Object key,Object value);  
 public Object getObject(Object key);  
 public Object removeObject(Object key);  
 public void clear();  
 public int size();  
}

簡易Cache實現

場景應用:
  • 存儲數據量比較小(由於沒有考慮淘汰機制)
  • 沒有線程共享(一個線程的內部緩存)
  • 緩存對象生命週期比較短
package com.cy.java.cache;  
import java.util.HashMap;  
import java.util.Map;  
/**負責真正存儲數據的一個對象,將數據存儲到一個map中*/  
public class PerpetualCache implements Cache {  
/** 特色:線程不安全,key不容許重複,不能保證key的順序  */  
private Map<Object,Object> cache=new HashMap<>();  
@Override  
public void putObject(Object key, Object value) {  
cache.put(key, value);  
}  
@Override  
public Object getObject(Object key) {  
return cache.get(key);  
}  
@Override  
public Object removeObject(Object key) {  
return cache.remove(key);  
}  
@Override  
public void clear() {  
 cache.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
return cache.toString();  
}  
public static void main(String\[\] args) {  
 Cache cache=new PerpetualCache();  
 cache.putObject("A", 100);  
 cache.putObject("B", 200);  
 cache.putObject("C", 300);  
 System.out.println(cache);  
 cache.removeObject("D");  
 cache.clear();  
 System.out.println(cache.size());  
}  
}

構建線程安全Cache對象

場景應用:併發環境
package com.cy.java.cache;  
/**線程安全的cache對象*/  
public class SynchronizedCache implements Cache{  
private Cache cache;  
public SynchronizedCache(Cache cache) {  
this.cache=cache;  
}  
@Override  
public synchronized void putObject(Object key, Object value) {  
cache.putObject(key, value);  
}  
@Override  
public synchronized Object getObject(Object key) {  
// TODO Auto-generated method stub  
return cache.getObject(key);  
}  
@Override  
public synchronized Object removeObject(Object key) {  
// TODO Auto-generated method stub  
return cache.removeObject(key);  
}  
@Override  
public synchronized void clear() {  
cache.clear();  
}  
@Override  
public synchronized int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
return cache.toString();  
}  
public static void main(String\[\] args) {  
SynchronizedCache cache=

 new SynchronizedCache(new PerpetualCache());  
cache.putObject("A", 100);  
cache.putObject("B", 200);  
cache.putObject("C", 300);  
System.out.println(cache);  
}  
  
}

思考:對於SynchronizedCache 有什麼優點,劣勢?java

支持日誌記錄的Cache實現

package com.cy.java.cache;  
/** 用於記錄命中率的日誌cache*/  
public class LoggingCache implements Cache {  
private Cache cache;  
/**記錄請求次數*/  
private int requests;  
/**記錄命中次數*/  
private int hits;  
public LoggingCache(Cache cache) {  
this.cache=cache;  
}  
@Override  
public void putObject(Object key, Object value) {  
cache.putObject(key, value);  
}  
@Override  
public Object getObject(Object key) {  
requests++;  
Object obj=cache.getObject(key);  
if(obj!=null)hits++;  
System.out.println("Cache hit Ratio : "+hits\*1.0/requests);  
return obj;  
}  
@Override  
public Object removeObject(Object key) {  
return cache.removeObject(key);  
}  
@Override  
public void clear() {  
cache.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
// TODO Auto-generated method stub  
return cache.toString();  
}  
public static void main(String\[\] args) {  
SynchronizedCache cache=  
 new SynchronizedCache(  
new LoggingCache(  
new PerpetualCache()));  
cache.putObject("A", 100);  
cache.putObject("B", 200);  
cache.putObject("C", 300);  
System.out.println(cache);  
cache.getObject("D");  
cache.getObject("A");  
}  
  
}

思考:你以爲LoggingCache記錄日誌的方式有什麼很差的地方?(信息的完整性,同步問題)算法

LruCache實現

應用場景:基於LRU算法的的基本實現
package com.cy.java.cache;  
import java.util.LinkedHashMap;  
import java.util.Map;  
  
/** 緩存淘汰策略:LRU(最近最少使用算法)*/  
public class LruCache implements Cache {  
 private Cache cache;  
 /**經過此屬性記錄要移除的數據對象*/  
 private Object eldestKey;  
 /**經過此map記錄key的訪問順序*/  
 private Map<Object,Object> keyMap;  
 @SuppressWarnings("serial")  
 public LruCache(Cache cache,int maxCap) {  
 this.cache=cache;  
//LinkedHashMap能夠記錄key的添加順序或者訪問順序  
 this.keyMap=

 new LinkedHashMap<Object,Object>(maxCap, 0.75f, true)

 {//accessOrder  
//此方法每次執行keyMap的put操做時調用  
@Override  
protected boolean removeEldestEntry

 (java.util.Map.Entry<Object, Object> eldest) {  
boolean isFull=size()>maxCap;  
if(isFull)eldestKey=eldest.getKey();  
return isFull;  
}  
 };  
}  
@Override  
public void putObject(Object key, Object value) {  
//存儲數據對象  
cache.putObject(key, value);  
//記錄key的訪問順序,假如已經滿了,就要從cache中移除數據  
keyMap.put(key, key);//此時會執行keyMap對象的removeEldestEntry  
if(eldestKey!=null) {  
cache.removeObject(eldestKey);  
eldestKey=null;  
}  
}  
@Override  
public Object getObject(Object key) {  
keyMap.get(key);//記錄key的訪問順序  
return cache.getObject(key);  
}  
  
@Override  
public Object removeObject(Object key) {  
return cache.removeObject(key);  
}  
  
@Override  
public void clear() {  
cache.clear();  
keyMap.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
return cache.toString();  
}  
  
public static void main(String\[\] args) {  
SynchronizedCache cache=  
 new SynchronizedCache(  
new LoggingCache(  
new LruCache(new PerpetualCache(),3)));  
cache.putObject("A", 100);  
cache.putObject("B", 200);  
cache.putObject("C", 300);  
cache.getObject("A");  
cache.getObject("C");  
cache.putObject("D", 400);  
cache.putObject("E", 500);  
System.out.println(cache);  
  
}  
}

設置Cache淘汰算法:FIFO算法

package com.cy.java.cache;  
import java.util.Deque;  
import java.util.LinkedList;  
/**  
* FifoCache :基於FIFO算法(對象滿了要按先進先出算法移除對象)實現cache對象  
*/  
public class FifoCache implements Cache{  
/**藉助此對象存儲數據*/  
private Cache cache;  
/**藉助此隊列記錄key的順序*/  
private Deque<Object> keyOrders;  
/**經過此變量記錄cache能夠存儲的對象個數*/  
private int maxCap;  
public FifoCache(Cache cache,int maxCap) {  
this.cache=cache;  
keyOrders=new LinkedList<>();  
this.maxCap=maxCap;  
}  
@Override  
public void putObject(Object key, Object value) {  
//1.記錄key的順序(起始就是存儲key,添加在隊列最後位置)  
keyOrders.addLast(key);  
//2.檢測cache中數據是否已滿,滿了則移除。  
if(keyOrders.size()>maxCap) {  
Object eldestKey=keyOrders.removeFirst();  
cache.removeObject(eldestKey);  
}  
//3.放新的對象  
cache.putObject(key, value);  
}  
@Override  
public Object getObject(Object key) {  
return cache.getObject(key);  
}  
  
@Override  
public Object removeObject(Object key) {  
Object obj=cache.removeObject(key);  
keyOrders.remove(key);  
return obj;  
}  
@Override  
public void clear() {  
cache.clear();  
keyOrders.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
// TODO Auto-generated method stub  
return cache.toString();  
}  
public static void main(String\[\] args) {  
Cache cache=

 new SynchronizedCache(  
new LoggingCache(  
 new FifoCache(  
  new PerpetualCache(),3)));  
cache.putObject("A",100);  
cache.putObject("B",200);  
cache.putObject("C",300);  
cache.getObject("A");  
cache.putObject("D",400);  
cache.putObject("E",500);  
System.out.println(cache);  
}   
}

序列化Cache的實現

場景:存儲到cache的是對象的字節
package com.cy.java.cache;  
import java.io.ByteArrayInputStream;  
import java.io.ByteArrayOutputStream;  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  
  
public class SerializedCache implements Cache {  
  
private Cache cache;  
public SerializedCache(Cache cache) {  
this.cache=cache;  
}  
/**序列化*/  
private byte\[\] serialize(Object value) {  
//1.構建流對象  
ByteArrayOutputStream bos=null;  
ObjectOutputStream oos=null;  
try {  
//1.2構建字節數組輸出流,此流對象內置可擴容的數組。  
bos=new ByteArrayOutputStream();  
//1.3構建對象輸出流  
oos=new ObjectOutputStream(bos);  
//2.對象序列化  
oos.writeObject(value);

 //此時對象會以字節的方式寫入到字節數組輸出流  
oos.flush();  
return bos.toByteArray();  
}catch (Exception e) {  
 throw new RuntimeException(e);  
}finally {  
//3.關閉流對象  
if(bos!=null)

 try{bos.close();bos=null;}catch(Exception e) {}  
if(oos!=null)

 try{oos.close();oos=null;}catch (Exception e2) {}  
}  
}  
/**反序列化*/  
public Object deserialize(byte\[\] value) {  
//1.建立流對象  
ByteArrayInputStream bis=null;  
ObjectInputStream ois=null;  
try {  
//1.1構建字節數組輸入流,此對象能夠直接讀取數組中的字節信息  
bis=new ByteArrayInputStream(value);  
//1.2構建對象輸入流(對象反序列化)  
ois=new ObjectInputStream(bis);  
//2.反序列化對象  
Object obj=ois.readObject();  
return obj;  
}catch(Exception e) {  
throw new RuntimeException(e);  
}finally {  
//3.關閉流對象  
if(bis!=null)

 try{bis.close();bis=null;}catch(Exception e) {}  
if(ois!=null)

 try{ois.close();ois=null;}catch (Exception e2) {}  
}  
}  
@Override  
public void putObject(Object key, Object value) {  
cache.putObject(key, serialize(value));  
}  
@Override  
public Object getObject(Object key) {  
return deserialize((byte\[\])cache.getObject(key));  
}  
@Override  
public Object removeObject(Object key) {  
return cache.removeObject(key);  
}  
@Override  
public void clear() {  
cache.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
public static void main(String\[\] args) {  
Cache cache=new SerializedCache(new PerpetualCache());  
cache.putObject("A", 200);  
cache.putObject("B", 300);  
Object v1=cache.getObject("A");  
Object v2=cache.getObject("A");  
System.out.println(v1==v2);  
System.out.println(v1);  
System.out.println(v2);  
}  
}

軟件引用Cache實現

應用場景:內存不足時淘汰緩存中數據
package com.cy.java.cache;  
  
import java.lang.ref.ReferenceQueue;  
import java.lang.ref.SoftReference;  
/**軟引用*/  
public class SoftCache implements Cache {  
private Cache cache;  
private ReferenceQueue<Object> garbageOfRequenceQueue=

 new ReferenceQueue<>();  
public SoftCache(Cache cache) {  
this.cache=cache;  
}  
@Override  
public void putObject(Object key, Object value) {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.將對象存儲到cache(key不變,Value爲爲soft引用對象)  
cache.putObject(key, 

 new SoftEntry(key, value, garbageOfRequenceQueue));  
}  
  
@Override  
public Object getObject(Object key) {  
//1.基於key獲取軟引用對象並判斷  
SoftEntry softEntry=(SoftEntry)cache.getObject(key);  
if(softEntry==null)return null;  
//2.基於軟引用對象獲取它引用的對象並判斷  
Object target = softEntry.get();  
if(target==null)cache.removeObject(key);  
return target;  
}  
  
@Override  
public Object removeObject(Object key) {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.從cache中移除對象  
Object removedObj=cache.removeObject(key);  
return removedObj;  
}  
  
@Override  
public void clear() {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.清空cache  
cache.clear();  
}  
@Override  
public int size() {  
removeGarbageObjects();  
return cache.size();  
}  
private void removeGarbageObjects() {  
SoftEntry softEntry=null;  
//1.從引用隊列中獲取已經被GC的一些對象的引用  
 while((softEntry=

 (SoftEntry)garbageOfRequenceQueue.poll())!=null){  
//softEntry不爲null表示softEntry引用的對象已經被移除  
//2.從cache中將對象引用移除。  
cache.removeObject(softEntry.key);  
}  
}  
/\*\*定義軟引用類型\*/  
private static class SoftEntry extends SoftReference<Object\>{  
private final Object key;  
public SoftEntry(Object key,

 Object referent, ReferenceQueue<? super Object> rQueue) {  
super(referent, rQueue);  
this.key=key;  
}  
}  
@Override  
public String toString() {  
// TODO Auto-generated method stub  
return cache.toString();  
}  
  
public static void main(String\[\] args) {  
Cache cache=new SoftCache(new PerpetualCache());  
cache.putObject("A", new byte\[1024\*1024\]);  
cache.putObject("B", new byte\[1024\*1024\]);  
cache.putObject("C", new byte\[1024\*1024\]);  
cache.putObject("D", new byte\[1024\*1024\]);  
cache.putObject("E", new byte\[1024\*1024\]);  
System.out.println(cache.size());  
System.out.println(cache);  
}  
  
}

弱Cache對象實現

應用場景:GC觸發清除緩存對象
package com.cy.java.cache;  
  
import java.lang.ref.ReferenceQueue;  
import java.lang.ref.WeakReference;  
/\*\*弱引用\*/  
public class WeakCache implements Cache {  
private Cache cache;  
private ReferenceQueue<Object> garbageOfRequenceQueue=

 new ReferenceQueue<>();  
public WeakCache(Cache cache) {  
this.cache=cache;  
}  
  
@Override  
public void putObject(Object key, Object value) {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.將對象存儲到cache(key不變,Value爲爲soft引用對象)  
cache.putObject(key, 

 new WeakEntry(key, value, garbageOfRequenceQueue));  
}  
  
@Override  
public Object getObject(Object key) {  
//1.基於key獲取軟引用對象並判斷  
WeakEntry softEntry=(WeakEntry)cache.getObject(key);  
if(softEntry==null)return null;  
//2.基於軟引用對象獲取它引用的對象並判斷  
Object target = softEntry.get();  
if(target==null)cache.removeObject(key);  
return target;  
}  
  
@Override  
public Object removeObject(Object key) {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.從cache中移除對象  
Object removedObj=cache.removeObject(key);  
return removedObj;  
}  
  
@Override  
public void clear() {  
//1.移除一些垃圾對象(Soft引用引用的已經被回收的對象)  
removeGarbageObjects();  
//2.清空cache  
cache.clear();  
}  
  
@Override  
public int size() {  
removeGarbageObjects();  
return cache.size();  
}  
private void removeGarbageObjects() {  
WeakEntry softEntry=null;  
//1.從引用隊列中獲取已經被GC的一些對象的引用  
while((softEntry=

 (WeakEntry)garbageOfRequenceQueue.poll())!=null) {  
//softEntry不爲null表示softEntry引用的對象已經被移除  
//2.從cache中將對象引用移除。  
cache.removeObject(softEntry.key);  
}  
}  
/**定義軟引用類型*/  
private static class WeakEntry extends WeakReference<Object\>{  
private final Object key;  
public WeakEntry(Object key,

 Object referent, ReferenceQueue<? super Object> rQueue) {  
super(referent, rQueue);  
this.key=key;  
}  
}  
@Override  
public String toString() {  
return cache.toString();  
}  
public static void main(String\[\] args) {  
Cache cache=new WeakCache(new PerpetualCache());  
cache.putObject("A", new byte\[1024\*1024\]);  
cache.putObject("B", new byte\[1024\*1024\]);  
cache.putObject("C", new byte\[1024\*1024\]);  
cache.putObject("D", new byte\[1024\*1024\]);  
cache.putObject("E", new byte\[1024\*1024\]);  
cache.putObject("F", new byte\[1024\*1024\]);  
cache.putObject("G", new byte\[1024\*1024\]);  
System.out.println(cache.size());  
System.out.println(cache);  
}  
  
}

緩存系統設計進階

緩存應用需求升級

  • 緩存系統既要保證線程安全又要保證性能。
  • 緩存日誌的記錄要寫到文件,並且是異步寫
  • 向緩存中寫數據時要提升序列化性能。

緩存對象讀寫鎖應用

package com.cy.java.cache;  
  
import java.util.concurrent.locks.ReentrantReadWriteLock;  
  
/**  
* 構建線程安全對象,基於ReentrantReadWriteLock對象實現讀寫鎖應用。  
* @author qilei  
*/  
public class ReentrantLockCache implements Cache {  
  
private Cache cache;  
/**  
* 此對象提供了讀鎖,寫鎖應用方式.  
* 1)寫鎖:排他鎖  
* 2)讀鎖:共享鎖  
* 說明:讀寫不能同時執行。  
*/  
private final ReentrantReadWriteLock readWriteLock =  
new ReentrantReadWriteLock();  
public ReentrantLockCache(Cache cache) {  
this.cache=cache;  
// TODO Auto-generated constructor stub  
}  
@Override  
public void putObject(Object key, Object value) {  
readWriteLock.writeLock().lock();  
try {  
cache.putObject(key, value);  
}finally {  
readWriteLock.writeLock().unlock();  
}  
}  
  
@Override  
public Object getObject(Object key) {  
readWriteLock.readLock().lock();  
try {  
 Object object=cache.getObject(key);  
 return object;  
}finally{  
readWriteLock.readLock().unlock();  
}  
}  
  
@Override  
public Object removeObject(Object key) {  
readWriteLock.writeLock().lock();  
try {  
 Object object=cache.removeObject(key);  
 return object;  
}finally{  
readWriteLock.writeLock().unlock();  
}  
}  
  
@Override  
public void clear() {  
readWriteLock.writeLock().lock();  
try {  
 cache.clear();  
}finally{  
readWriteLock.writeLock().unlock();  
}  
}  
  
@Override  
public int size() {  
readWriteLock.readLock().lock();  
try {  
 int size=cache.size();  
 return size;  
}finally{  
readWriteLock.readLock().unlock();  
}  
}  
}

異步日誌Cache實現

第一步:添加依賴
` <dependency>  
 <groupId>ch.qos.logback</groupId>  
 <artifactId>logback-classic</artifactId>  
 <version>1.2.3</version>  
 </dependency> `
第二步:添加配置文件logback.xml (參考項目代碼)
<?xml version="1.0" encoding="UTF-8"?>  
<configuration>  
  
<logger name="com.cy" level="TRACE" />  
<appender name="FILE"  
class\="ch.qos.logback.core.rolling.RollingFileAppender"\>  
<rollingPolicy  
class\="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"\>  
<!--文件路徑,定義了日誌的切分方式----把每一天的日誌歸檔到一個文件中,以防止日誌填滿整個磁盤空間 -->  
<fileNamePattern>logs/context-log.%d{yyyy-MM-dd}.log  
</fileNamePattern>  
<!--只保留最近30天的日誌 -->  
<maxHistory>30</maxHistory>  
</rollingPolicy>  
<encoder charset="UTF-8"\>  
<pattern>\[%-5level\] %date --%thread-- \[%logger\] %msg %n</pattern>  
</encoder>  
</appender>  
  
<appender name="ASYNC\_FILE"  
class\="ch.qos.logback.classic.AsyncAppender"\>  
<discardingThreshold>0</discardingThreshold>  
<queueSize>256</queueSize>  
<appender-ref ref="FILE" />  
</appender>  
  
<root level="debug"\>  
<appender-ref ref="ASYNC\_FILE" />  
</root>  
  
</configuration>
第三步:構建AsyncLoggingCache
package com.cy.java.cache;  
  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
/**  
* 經過此對象異步記錄查詢操做的命中率  
* 1)選擇日誌庫  
* 2)執行異步寫操做。  
*/  
public class AsyncLoggingCache implements Cache {  
 //日誌門面應用  
 private static Logger log=LoggerFactory.getLogger(LoggingCache.class);  
private Cache cache;  
/**表示請求次數*/  
private int requests;  
/**命中次數(命中表示從緩存中取到數據了)*/  
private int hits;  
public AsyncLoggingCache(Cache cache) {  
this.cache=cache;  
}  
@Override  
public void putObject(Object key, Object value) {  
cache.putObject(key, value);  
}  
@Override  
public Object getObject(Object key) {  
requests++;  
 Object obj=cache.getObject(key);  
 if(obj!=null)hits++;  
 //記錄日誌耗時  
 log.info("Cache hit Ratio:{}",hits\*1.0/requests);  
return obj;  
}  
@Override  
  
public Object removeObject(Object key) {  
return cache.removeObject(key);  
}  
@Override  
public void clear() {  
cache.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
public static void main(String\[\] args) {  
Cache cache= 

 new AsyncLoggingCache(new PerpetualCache());  
cache.putObject("A", 100);  
cache.putObject("B", 200);  
cache.putObject("C", 300);  
cache.putObject("D", 400);  
//System.out.println(cache);  
cache.getObject("E");  
cache.getObject("A");  
cache.getObject("B");  
}  
  
}

Kryo構建序列化Cache

第一步:添加依賴
<dependency>  
 <groupId>com.esotericsoftware</groupId>  
 <artifactId>kryo</artifactId>  
 <version>5.0.0-RC5</version>  
</dependency>
第二步:構建項目工具類
public class KryoUtils {  
  
/**  
* 多線程併發執行時,可能會出現線程不安全,具體緣由是什麼?  
* 1)多個線程的併發  
* 2)多個線程有數據共享  
* 3)多個線程在共享數據集上的操做不是原子操做  
*  
* 分析:當出現了線程不安全,如何進行修改來保證線程安全  
* 1)將多線程改成單線程。  
* 2)取消共享 (例如在當前應用中咱們一個線程一個Kryo對象)  
* 3)加鎖+CAS  
*  
* ThreadLocal提供了這樣的一種機制:  
* 1)能夠將對象綁定到當前線程(實際上是將對象存儲到當前線程的map中)  
* 2)能夠從當前線程獲取綁定的對象(從當前線程的map中獲取對象)  
*/  
static private final ThreadLocal<Kryo> kryos = new ThreadLocal<Kryo>() {  
  protected Kryo initialValue() {  
  Kryo kryo = new Kryo();  
  // Configure the Kryo instance.  
  kryo.setRegistrationRequired(false);  
  //....  
  return kryo;  
  };  
 };  
 public static Object deserialize(byte\[\] array){  
Kryo kryo=kryos.get();  
 Input input = new Input(new ByteArrayInputStream(array));  
 Object obj=kryo.readClassAndObject(input);  
return obj;  
 }  
 public static byte\[\] serialize(Object object){  
 //從當前線程獲取kryo對象,當前線程沒有會調用ThreadLocal的initialValue方法建立對象並綁定線程  
 Kryo kryo=kryos.get();  
 ByteArrayOutputStream bos=new ByteArrayOutputStream();  
 Output output = new Output(bos);  
 kryo.writeClassAndObject(output, object);  
  output.close();  
 return bos.toByteArray();  
 }  
 }

> 構建高性能序列化Cache

public class KryoSerializedCache implements Cache {  
  
private Cache cache;  
public KryoSerializedCache(Cache cache) {  
this.cache=cache;  
}  
  
@Override  
public void putObject(Object key, Object value) {  
//1.將對象序列化  
byte\[\] array=KryoUtils.serialize(value);  
//2.將序列化後的字節數組引用存儲到cache  
cache.putObject(key,array);  
}  
  
@Override  
public Object getObject(Object key) {  
//1.基於key獲取緩存中的字節數組引用  
byte\[\] array=(byte\[\])cache.getObject(key);  
//2.將字節數組反序列化爲對象  
return KryoUtils.deserialize(array);  
}  
  
@Override  
public Object removeObject(Object key) {  
return KryoUtils.deserialize((byte\[\])cache.removeObject(key));  
}  
  
@Override  
public void clear() {  
cache.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
public static void main(String\[\] args) {  
Cache cache=new KryoSerializedCache(new PerpetualCache());  
cache.putObject("A", 500);  
Object a1=cache.getObject("A");  
Object a2=cache.getObject("A");  
System.out.println("a1="+a1);  
System.out.println("a2="+a2);  
System.out.println(a1==a2);//false  
}  
  
}
相關文章
相關標籤/搜索