花果山第一屆猿類分級考試實錄--Talk is cheap,Show me the code
阿新 • • 發佈:2019-09-19
本故事純屬虛構,如有雷同,純屬巧合!
故事背景
悟空師徒4人取經回來後,因不耐收到管教,就回到了花果山,帶領一幫猴子猴孫逍遙自在的過日子,奈何因在閻王殿裡將生死薄中的猴子猴孫的名字都劃去了,猴子猴孫是越來越多。
悟空最是沒有耐心的,無法一一管教,隨向太白金星討教。
猿類分級考試
太白金星給了主意:考試分級。
並且給出了題目:
建立一個通用的計數器,能計量很多的東西,如金箍棒。
參考答案如下:
猿類分階:一~九等級 依次上升
一階猿類
public class Counter1 { private static int cnt=0; public int increase() { return ++cnt; } public int decrease() { return --cnt; } }
旁白:實現了功能。
二階猿類
public class Counter2 { private static long cnt=0; public long increase() { return ++cnt; } public long decrease() { return --cnt; } }
旁白:考慮了int的範圍限制,long的範圍更廣泛。
三階猿類
public class Counter3 { private static long cnt=0; public synchronized long increase() { return ++cnt; } public synchronized long decrease() { return --cnt; } }
旁白:考慮了併發環境下的執行
四階猿類
public class Counter4 { private static AtomicLong cnt=new AtomicLong(0); public long increase() { return cnt.getAndIncrement(); } public long decrease() { return cnt.getAndDecrement(); } }
旁白:考慮了併發環境下的cas效能更優
五階猿類
public class Counter5 { private static LongAdder cnt=new LongAdder(); public long increase() { cnt.increment(); return cnt.longValue(); } public long decrease() { cnt.decrement(); return cnt.longValue(); } }
旁白:在單執行緒下,併發問題沒有暴露,兩者沒有體現出差距;隨著併發量加大,LongAdder 的 increment 操作更加優秀,而 AtomicLong 的 get 操作則更加優秀。鑑於在計數器場景下的特點—寫多讀少,所以寫效能更高的 LongAdder 更加適合。
六階猿類
public class Counter6 { private static JdbcTemplateUtils jdbc=new JdbcTemplateUtils(); private static long cnt=0; public long increase() { cnt=jdbc.getCnt(); return jdbc.setCnt(++cnt); } public long decrease() { cnt=jdbc.getCnt(); return jdbc.setCnt(--cnt);; } }
旁白:考慮了在叢集環境下保證資料的唯一性和一致性。
七階猿類
public class Counter7 { private static RedisclusterUtils redis=new RedisclusterUtils(); private static long cnt=0; public long increase() { return redis.incr(cnt); } public long decrease() { return redis.decr(cnt);; } }
旁白:考慮了計數器叢集下的併發效能問題,同樣的實現可以使用zk或者mongo等記憶體資料庫。
八階猿類
public class Counter8 { private static JdbcTempalteUtils jdbc=new JdbcTempalteUtils(); private static RedisclusterUtils redis=new RedisclusterUtils(); private static long cnt=0; public long increase() { if(redis.exsits(cnt)) { return redis.incr(cnt); } cnt=jdbc.getCnt(key); ++cnt; redis.set(key,cnt); return cnt; } public long decrease() { if(redis.exsits(cnt)) { return redis.decr(cnt); } cnt=jdbc.getCnt(key); --cnt; redis.set(key,cnt); return cnt; } }
旁白:考慮到redis宕機或者不可用的情況下的處理,有備份方案。
九階猿類
這個要免考的。
參考資料:
【1】https://mp.weixin.qq.com/s/yAvJFZWxfKb38IDMjQ