Ehcache高併發在專案中的應用
阿新 • • 發佈:2019-01-23
我們在專案開發中,有些資料常常用到,而又不需要經常去更新它,我們就會想到了使用快取來儲存這些資料,已提高我們對這些資料的讀取速度,因此本文使用ehcache來解決這個問題,EhcacheUtil 能有效的防止高併發。
1、EhcacheUtil 類
2、ehcache.xml配置檔案,放到src根目錄下面/** * 高併發解析: * 1、當一個執行緒獲取了某一Key的Read鎖之後,其它執行緒獲取針對於同一個Key的Read鎖不會受到限制, * 但其它執行緒(包括獲取了該Key的Read鎖的執行緒)如果想獲取針對同一個Key的Write鎖就不行,它需要等到針對於該Key的Read鎖釋放後才能獲取其Write鎖; * 2、當一個執行緒獲取了某一Key的Write鎖之後,其它執行緒獲取同一個Key的Read鎖或者Write鎖的請求將等待針對於該Key的Write鎖釋放後才能繼續進行, * 但是同一個執行緒獲取該Key對應的Read鎖或者Write鎖將不需要等待。 * 獲取了對應的鎖之後,不再需要該鎖後釋放該鎖,以免引起死鎖。 */ public class EhcacheUtil { private static final String PATH = "/ehcache.xml"; private static final String CACHE_NAME = "productEhcache"; private CacheManager manager; private static EhcacheUtil ehCache; private EhcacheUtil(String path) { URL url = getClass().getResource(path); manager = CacheManager.create(url); } /** * 獲取快取例項,配置檔案路徑“src/ehcache.xml” * @return */ public static EhcacheUtil getInstance() { if (ehCache == null) { ehCache = new EhcacheUtil(PATH); } return ehCache; } /** * 儲存鍵值到預設的快取裡面 * @param key 鍵名 * @param value 鍵值 */ public void put(String key, Object value) { put(CACHE_NAME, key, value); } /** * 儲存鍵值到指定的快取裡面 * @param cacheName 快取名稱 * @param key 鍵名 * @param value 鍵值 */ public void put(String cacheName, String key, Object value) { Cache cache = manager.getCache(cacheName); cache.acquireWriteLockOnKey(key); try { Element element = new Element(key, value); cache.put(element); } finally { cache.releaseWriteLockOnKey(key); } } /** * 從預設的快取裡面獲取鍵值 * @param key 鍵名 */ public Object get(String key) { return get(CACHE_NAME, key); } /** * 從指定的快取裡面獲取鍵值 * @param cacheName 快取名稱 * @param key 鍵名 */ public Object get(String cacheName, String key) { Cache cache = manager.getCache(cacheName); cache.acquireReadLockOnKey(key); Element element = null; try{ element = cache.get(key); } finally { cache.releaseReadLockOnKey(key); } return element == null ? null : element.getObjectValue(); } /** * 從預設的快取裡面刪除鍵值 * @param key 鍵名 */ public void remove(String key) { remove(CACHE_NAME, key); } /** * 從指定的快取裡面刪除鍵值 * @param cacheName 快取名稱 * @param key 鍵名 */ public void remove(String cacheName, String key) { Cache cache = manager.getCache(cacheName); cache.remove(key); } }
3、EhcacheTest測試類<?xml version="1.0" encoding="UTF-8"?> <!-- 快取配置 timeToIdleSeconds 當快取閒置n秒後銷燬。 timeToLiveSeconds 當快取存活n秒後銷燬。 name:快取名稱。 maxElementsInMemory:快取最大個數。 eternal:物件是否永久有效,一但設定了,timeout將不起作用。 timeToIdleSeconds:設定物件在失效前的允許閒置時間(單位:秒)。僅當eternal=false物件不是永久有效時使用,可選屬性,預設值是0,也就是可閒置時間無窮大。 timeToLiveSeconds:設定物件在失效前允許存活時間(單位:秒)。最大時間介於建立時間和失效時間之間。僅當eternal=false物件不是永久有效時使用,預設是0.,也就是物件存活時間無窮大。 overflowToDisk:當記憶體中物件數量達到maxElementsInMemory時,Ehcache將會物件寫到磁碟中。 diskSpoolBufferSizeMB:這個引數設定DiskStore(磁碟快取)的快取區大小。預設是30MB。每個Cache都應該有自己的一個緩衝區。 maxElementsOnDisk:硬碟最大快取個數。 diskPersistent:是否快取虛擬機器重啟期資料 Whether the disk store persists between restarts of the Virtual Machine. The default value is false. diskExpiryThreadIntervalSeconds:磁碟失效執行緒執行時間間隔,預設是120秒。 memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體。預設策略是LRU(最近最少使用)。你可以設定為FIFO(先進先出)或是LFU(較少使用)。 clearOnFlush:記憶體數量最大時是否清除。 --> <ehcache> <diskStore path="java.io.tmpdir" /> <defaultCache maxElementsInMemory="500" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="1200" overflowToDisk="true" /> <cache name="testEhcache" maxElementsInMemory="150" eternal="false" timeToLiveSeconds="36000" timeToIdleSeconds="3600" overflowToDisk="true"/> <cache name="productEhcache" maxElementsInMemory="500" memoryStoreEvictionPolicy="LRU" eternal="true" diskSpoolBufferSizeMB="1024" overflowToDisk="true"/> </ehcache>
4、ProductDto實體類public class EhcacheTest { //新建ehcache例項 private static EhcacheUtil ehcache = EhcacheUtil.getInstance(); public static void main(String[] args) { setProductData(); ProductDto pd = (ProductDto)ehcache.get(Constant.PRODUCT_MAP_CACHE_NAME+1); System.out.println(pd); ehcache.remove(Constant.PRODUCT_MAP_CACHE_NAME+1); pd = (ProductDto)ehcache.get(Constant.PRODUCT_MAP_CACHE_NAME+1); System.out.println(pd); } public static void setProductData(){ //構造資料 int sizeProduct = 100000; //List<ProductDto> productList = new ArrayList<ProductDto>(); for (int j = 0; j < sizeProduct; j++) { // ProductDto product = new ProductDto(); // product.setId(j); // product.setProductName("產品名稱"+j); // //productList.add(product); // ehcache.put(Constant.PRODUCT_MAP_CACHE_NAME+j, product); ehcache.put(Constant.PRODUCT_MAP_CACHE_NAME+j, j); } //把map放到ehcache中 //ehcache.put(Constant.PRODUCT_MAP_CACHE_NAME, productList); } @SuppressWarnings("unchecked") public static List<ProductDto> getProductData(){ return (List<ProductDto>)ehcache.get(Constant.PRODUCT_MAP_CACHE_NAME); } public static void deleteProductData(int index){ List<ProductDto> productList = getProductData(); productList.remove(productList.get(index)); ehcache.put(Constant.PRODUCT_MAP_CACHE_NAME, productList); } public static void addProductData(int index){ List<ProductDto> productList = getProductData(); ProductDto product = new ProductDto(); product.setId(index); product.setProductName("產品名稱"+index); productList.add(product); ehcache.put(Constant.PRODUCT_MAP_CACHE_NAME, productList); } public static void showProductData(){ List<ProductDto> productList = getProductData(); System.out.println("---------------------"); for (ProductDto productDto : productList) { System.out.println(productDto); } } }
public class ProductDto implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Integer id;//id
private String productName;//產品名稱
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String toString(){
return this.getId()+" ,name:"+this.getProductName();
}
}
5、Constant靜態變數類
public class Constant {
/**
* 產品MAP
*/
public static final String PRODUCT_MAP_CACHE_NAME = "productMap";
}