采用LinkedHashMap自带的LRU 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据);
* 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setMaxCacheSize重新设置缓存大小,可手动清空内存缓存
* <br>支持内存缓存和磁盘缓存方式, 通过 {@link cc.util.cache.NetByteWrapper} 支持HTTP缓存 (注:详细参考cc.util.http包); 注:使用JDK7
package cc.util.cache; import java.io.Serializable;import java.util.Objects; /**封装网络数据, 将数据的Etag、lastModified获取到, 下次请求的时候提取出来到服务器比对 * Help to wrap byte data which obtains from network, It will work with {@link cc.util.cache.NetChacheManager}* @author wangcccong * @version 1.1406 * <br> create at: Tues, 10 Jun 2014 */public class NetByteWrapper implements Serializable { private final static long serialVersionUID = 1L; /** data from network */private byte[] data;/** data size */int contentLength;/** latested modify time */private long lastModified;/** ETag: look up HTTP Protocol */private String ETag; public NetByteWrapper(byte[] data, long lastModified, String Etag) {this.data = data;this.lastModified = lastModified;this.ETag = Etag;} public byte[] getData() {return data;}public void setData(byte[] data) {this.data = data;} public long getLastModified() {return lastModified;}public void setLastModified(long lastModified) {this.lastModified = lastModified;} public String getETag() {return ETag;} public void setETag(String eTag) {this.ETag = eTag;} public int getContentLength() {return Objects.isNull(data) ? 0 : data.length;}}package cc.util.cache; import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference; /**采用软引用方式将数据存放起来 * enclose {@link cc.util.cache.NetByteWrapper} with {@link java.lang.ref.SoftReference}, In order to recycle the memory * @author wangcccong * @version 1.1406 * <br> create at: Tues, 10 Jun. 2014 */public class NetByteSoftReference extends SoftReference<NetByteWrapper> { private String key = "";private long length = 0; public NetByteSoftReference(String key, NetByteWrapper arg0) {this(key, arg0, null);} public NetByteSoftReference(String key, NetByteWrapper arg0,ReferenceQueue<? super NetByteWrapper> arg1) {super(arg0, arg1);// TODO Auto-generated constructor stubthis.key = key;this.length = arg0.getContentLength();} public String getKey() {return key;} public long getLength() {return length;} }package cc.util.cache; import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.Objects; /** * 采用LinkedHashMap自带的LRU 算法缓存数据, 可检测对象是否已被虚拟机回收,并且重新计算当前缓存大小,清除缓存中无用的键值对象(即已经被虚拟机回收但未从缓存清除的数据); * 默认内存缓存大小为: 4 * 1024 * 1024 可通过通过setMaxCacheSize重新设置缓存大小,可手动清空内存缓存,支持采用内存映射方式读取缓存 * <br>支持内存缓存和磁盘缓存方式, 通过 {@link cc.util.cache.NetByteWrapper} 支持HTTP缓存 (注:详细参考cc.util.http包) * @author wangcccong * @version 1.1406 * <br> create at: Tues, 10 Jun 2014 */public class NetCacheManager { /** max cache size */private long MAX_CACHE_SIZE = 4 * 1024 * 1024;private long cacheSize = 0;private static NetCacheManager instance = null; private final ReferenceQueue<NetByteWrapper> referenceQueue;private final LinkedHashMap<String, NetByteSoftReference> cacheMap; private NetCacheManager(){referenceQueue = new ReferenceQueue<NetByteWrapper>();cacheMap = new LinkedHashMap<String, NetByteSoftReference>(16, 0.75f, true) { private static final long serialVersionUID = -8378285623387632829L;@Overrideprotected boolean removeEldestEntry(java.util.Map.Entry<String, NetByteSoftReference> eldest) {// TODO Auto-generated method stubboolean shouldRemove = cacheSize > MAX_CACHE_SIZE;if (shouldRemove) {cacheSize -= eldest.getValue().getLength();System.gc();}return shouldRemove;}};} /** singleton model */public static synchronized NetCacheManager newInstance(){if (Objects.isNull(instance)) {instance = new NetCacheManager();}return instance;} /** * reset the memory cache size * @param cacheSize */public void setMaxCacheSize(long cacheSize) {this.MAX_CACHE_SIZE = cacheSize;} /** * 获取当前内存缓存大小 * @return */public long getCacheSize() {return cacheSize;} /** * 将数据缓存至内存, 如果http返回的数据<b>不支持</b>缓存则采用此方法,缓存的key一般为请求的url * @param key * @param value */public void cacheInMemory(String key, byte[] value) {this.cacheInMemory(key, value, 0, null);} /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param lastModified */public void cacheInMemory(String key, byte[] value, long lastModified) {this.cacheInMemory(key, value, lastModified, null);} /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param Etags */public void cacheInMemory(String key, byte[] value, String Etags) {this.cacheInMemory(key, value, 0, Etags);} /** * 将数据缓存至内存, 如果http返回的数据<b>支持</b>缓存则采用此方法 * @param key * @param value * @param lastModified * @param Etags */private void cacheInMemory(String key, byte[] value, long lastModified, String Etags) {Objects.requireNonNull(key, "key must not be null");clearRecycledObject();NetByteWrapper wrapper = new NetByteWrapper(value, lastModified, Etags);NetByteSoftReference byteRef = new NetByteSoftReference(key, wrapper, referenceQueue);cacheMap.put(key, byteRef);value = null;wrapper = null;} /** * 缓存至磁盘, 默认不首先缓存到内存 * @param key * @param value * @param path */public void cacheInDisk(String key, byte[] value, String path) {cacheInDisk(key, value, path, false);} /** ** @param key * @param value * @param path * @param cacheInMemory */public void cacheInDisk(String key, byte[] value, String path, boolean cacheInMemory) {this.cacheInDisk(key, value, 0, null, path, cacheInMemory);} /** ** @param key * @param value * @param lastModified * @param Etags * @param path * @param cacheInMemory */private void cacheInDisk(String key, byte[] value, long lastModified, String Etags, String path, boolean cacheInMemory) {if (cacheInMemory) cacheInMemory(key, value, lastModified, Etags);try (FileOutputStream fos = new FileOutputStream(path);ObjectOutputStream oos = new ObjectOutputStream(fos)) {NetByteWrapper wrapper = new NetByteWrapper(value, lastModified, Etags);oos.writeObject(wrapper);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}} /** * get {@link cc.util.cache.NetByteWrapper} from memory according to key * @param key * @return {@link cc.util.cache.NetByteWrapper} */public NetByteWrapper getFromMemory(String key) {SoftReference<NetByteWrapper> softReference = cacheMap.get(key);return Objects.nonNull(softReference) ? softReference.get() : null;} /** * get byte[] from memory according to key * @param context * @param key * @return */public byte[] getByteFromMemory(String key) {NetByteWrapper wrapper = getFromMemory(key);return Objects.nonNull(wrapper) ? wrapper.getData() : null;} /** * 从磁盘获取数据 * @param path * @return {@link cc.util.cache.NetByteWrapper} */public NetByteWrapper getFromDisk(String path) {try (FileInputStream fis = new FileInputStream(path);ObjectInputStream ois = new ObjectInputStream(fis)) {NetByteWrapper wrapper = (NetByteWrapper) ois.readObject();return wrapper;} catch (Exception e) {// TODO: handle exceptione.printStackTrace();return null;}} /** * 采用内存映射的方式从磁盘获取数据(加快读取缓存的大文件) * @param path * @return */public NetByteWrapper getFromDiskByMapped(String path) {try (FileInputStream fis = new FileInputStream(path);FileChannel channel= fis.getChannel();ByteArrayOutputStream baos = new ByteArrayOutputStream()){MappedByteBuffer mbb = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());byte[] bts = new byte[1024]; int len = (int) channel.size();for (int offset = 0; offset < len; offset += 1024) { if (len - offset > 1024) mbb.get(bts);else mbb.get((bts = new byte[len - offset])); baos.write(bts);} ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);NetByteWrapper wrapper = (NetByteWrapper) ois.readObject();bais.close();ois.close();return wrapper;} catch (Exception e) {// TODO: handle exceptione.printStackTrace();return null;}} /** * 从磁盘获取缓存的byte[] 数据 * @param path * @return */public byte[] getByteFromDisk(String path) {NetByteWrapper wrapper = getFromDisk(path);return Objects.isNull(wrapper) ? null : wrapper.getData();} /** * 通过内存映射放射从磁盘获取缓存的byte[] 数据 * @param path * @return */public byte[] getByteFromDiskByMapped(String path) {NetByteWrapper wrapper = getFromDiskByMapped(path);return Objects.isNull(wrapper) ? null : wrapper.getData();} /** * calculate the size of the cache memory */private void clearRecycledObject() {NetByteSoftReference ref = null;//检测对象是否被回收,如果被回收则从缓存中移除死项while (Objects.nonNull((ref = (NetByteSoftReference) referenceQueue.poll()))) {cacheMap.remove(ref.getKey());}cacheSize = 0;Iterator<String> keys = cacheMap.keySet().iterator();while (keys.hasNext()) {cacheSize += cacheMap.get(keys.next()).getLength();}} /** * clear the memory cache */public void clearCache() {clearRecycledObject();cacheMap.clear();System.gc();System.runFinalization();} }
以上所述就是本文的全部内容了,希望大家能够喜欢。