標籤:tab 廣告 thread resource ati logs .com 過程 www.
寫在前面:工作有幾年了,從入門到現在,遇到也解決了一些問題。(當然,架構層級的暫時還沒有)一直以來,都是從部落格園以及其他各大社區搜羅出來的各種fix方法。目前稍有閑暇時間,在看過大V沈劍的博文後,我也鼓起勇氣來書寫部落格,記錄工作中遇到和解決的問題(其中當然也包括我在博園擷取的各種解決方案;能找到原博文的小弟一定會註明出處。)因為總覺得自己水平不夠,怕寫出來的文章誤導了別人。以下是這周生產環境遇到的一個問題,寫出來供大家參考。現象
周五一大早,車子都沒停穩(電動車),群裡就開始在詢問誰最近的代碼有比較耗時耗效能的操作,大家都說沒有。然後就是一張:
cpu已經飆到1600+,這個問題還是比較嚴重的。隨後聯絡到營運組給出tomcat作業記錄排查是否有錯誤。經過排查日誌發下如下錯誤:
看到後飛速坐到位置上,去查詢對應的錯誤碼;
分析和搜尋:
以下是部分代碼:
1 public static Map<String,String> cityCodeMap = new HashMap<String, String>(); 2 3 public static Map<String,String> provinceMap = new HashMap<String, String>(); 4 5 public static List<String> sensitiveWordList = new ArrayList<String>(); 6 7 public static String getCityCodeByNumber(String phoneNumber) 8 { 9 String start = StringUtils.substring(phoneNumber, 0, 7);10 if(StringUtils.isEmpty(start))11 {12 return "000";13 }14 Map<String, String> cityCodes = getCityCodes();15 String cityCode = cityCodes.get(start);16 if(StringUtils.isEmpty(cityCode))17 {18 return "000";19 }20 return cityCode;21 }
主要用於擷取手機號碼的號段對應的城市編碼,項目的某個模組(不能打廣告吧)需要用到。並且每次調用都用用到;咋一看,感覺沒啥問題,項目中好多地方都是這麼乾的。接著又在測試環境和本地環境跑一邊代碼,都運行正常。
然後就搜尋了java.lang.thread.waiting 這個異常,在這篇博文中搜到相關問題,http://www.cnblogs.com/zhengyun_ustc/archive/2013/03/18/tda.html
才發現可能是多線程引發的問題。
這裡列舉兩個比較解釋特別詳細的博文,源碼跟蹤和分析過程都非常詳細。
http://coding-geek.com/how-does-a-hashmap-work-in-java/
https://coolshell.cn/articles/9606.html
此種情況雖然是機率發生的,但是在並發量比較大的情況下,還是及其危險的。如果發現不及時,很有可能導致單點故障甚至整個叢集不可用。又根據自己項目代碼的情況分析,主要是因為在初始化中,迴圈向map中put新元素導致map擴容rehash時產生了死迴圈。
初始化代碼:
public static Map<String,String> getCityCodes() { if(cityCodeMap.isEmpty()) { Set<String> keySet = ResourceBundle.getBundle("config/citynum").keySet(); for (String key : keySet) { String cityCode = PropertiesUtil.getKey("config/citynum",key); cityCodeMap.put(key, cityCode); } } return cityCodeMap; }
ps:此處的citynum中有幾萬個索引值對。
解決辦法:
- Hashtable
- ConcurrentHashMap
- Synchronized Map
可自行搜尋實現原理,很多大神、大仙兒都闡述的比我詳細。
都說程式員都是懶人,我不認同。我們只不過是想用最少的代碼去解決問題。所以,我們的改良方案就是把HashMap直接換成ConcurrentHashMap。
生產環境遇到的hashMap非安全執行緒問題java.lang.thread.waiting