使用Map實現redis的功能(適用於單機版)
阿新 • • 發佈:2019-01-30
背景:某個專案需要用到類似redis的功能(儲存鍵值對,並且希望鍵值對是有過期時間的)。如果只是為了一個小功能,就安裝一個redis伺服器,那明顯太浪費效能。所以開發了這個類,使用MAP來模仿和實現redis的處理。
原理:利用兩個Map,一個map用來儲存值,一個map用來儲存過期時間。另外有一個執行緒,定期去掃描那些key過期,如果過期,則移除這個值。
注:使用ConcurrentHashMap是為了執行緒安全。
程式碼如下:
/** * */ package com.yihu.util.mapRedis; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 使用Map實現redis的功能(只支援單機) * @author lch 201705 * */ public class MapForRedisUtils extends Thread { private static MapForRedisUtils mapForRedisUtils=null; private static Map<String,String> map=new ConcurrentHashMap<String,String>(); private static Map<String,Long> expireMap=new ConcurrentHashMap<String,Long>(); /** * 儲存值 * @param key 健 * @param val 值 * @param minute 過期時間(分鐘) */ public static void setValue(String key,String val,int minute){ try{ map.put(key,val); expireMap.put(key,System.currentTimeMillis()+minute*60L*1000); }catch(Exception e){ e.printStackTrace(); } } /** * 獲取值 * @param key 健 */ public static String getValue(String key){ try{ return map.get(key); }catch(Exception e){ e.printStackTrace(); return null; } } /** * 獲取過期時間(相對於1970-1-1的毫秒數) * @param key 健 */ public static long getExpireTime(String key){ try{ return expireMap.get(key); }catch(Exception e){ e.printStackTrace(); return 0; } } /** * 設定過期時間(毫秒數) * @param key 健 * @param expireMills 多少毫秒 */ public static long setExpireTime(String key,int minute){ try{ return expireMap.put(key,System.currentTimeMillis()+minute*60L*1000); }catch(Exception e){ e.printStackTrace(); return 0; } } @Override public void run() { while(true){ try{ //移除過期的資料 List<String> needRemoveKey=new ArrayList<String>(); for (Map.Entry<String, Long> entry : MapForRedisUtils.expireMap.entrySet()) { if(entry.getValue()!=null&&entry.getValue()<=System.currentTimeMillis()){ needRemoveKey.add(entry.getKey()); } } for(String key:needRemoveKey){ map.remove(key); expireMap.remove(key); } try { Thread.sleep(10000);//暫停10秒鐘,變成死迴圈 } catch (Exception e1) { e1.printStackTrace(); } }catch(Exception e){ try { Thread.sleep(1000);//防止故障的時候,變成死迴圈 } catch (Exception e1) { e1.printStackTrace(); } } } } public static void init(){ if(mapForRedisUtils==null){ mapForRedisUtils=new MapForRedisUtils(); mapForRedisUtils.start();//啟動監視執行緒(自動刪除過期的資料) } } public static void main(String[] args) throws InterruptedException { MapForRedisUtils.init(); MapForRedisUtils.setValue("test", "1111111", 1);//設定值 System.out.println(MapForRedisUtils.getValue("test"));//讀取值 Thread.sleep(2*60*1000); System.out.println("2 min after,val="+MapForRedisUtils.getValue("test"));//資料過期之後,再去讀取,就發現沒有了 } }