品阿里 Java 開發手冊有感

摘要: 原創出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,謝謝!

file

一個優秀的工程師和一個普通的工程師的區別,不是滿天飛的架構圖,他的功底體現在所寫的每一行代碼上。
— 畢玄

1. 命名風格

【書摘】類名用 UpperCamelCase 風格,比如 DO/BO/VO/PO

【書摘】方法用 lowerCamelCase 風格,盡量是動詞

小思考:例如常用的
– 獲取單個對象,getUserById
– 獲取對象累不,listUserByGroupId
– 統計對象數量,countUserByClassId
– 新增、刪除,insert,delete,update 等

2. 常量定義

【書摘】如果變量值僅在一個范圍變化,則用 enum 類型

小思考:例如電商中訂單狀態,用手指也能列出來。所以一般定義個 OrderSatausEnum 搞定,偽代碼如下:

public enum OrderSatausEnum {
    TO_PAY(1,"代付款"), PAID(2,"已付款") ...;

    private Integer orderStatus;
    private String orderSatausDes;

    OrderSatausEnum(Integer orderStatus,String orderSatausDes) {
        this.orderStatus = orderStatus;
        this.orderSatausDes = orderSatausDes;
    }

    // get set
}

進一步,如果訂單某天要加個“待拼團”狀態咋辦?所以這些配置化的東西,可以上配置中心。比如攜程出的 apollo 等

3. OOP 規則

【書摘】Object 的 equals 方法容易拋空指針異常,應使用常量或者確定優質的對象來調用 equals 。

比如:“TO_PAY”.equals(order.getOrderStatus())。反著寫就不對了,因為 order.getOrderStatus() 可能為 null。

自然,更加推薦 java.util.Objects#equals 工具類。

【書摘】所有相同類型的包裝類對象之間的值比較,全部使用 equals 方法。

小思考:別用 == 了。equals 也要注意些事情,比如 Byte 類型的 status 對象值,用 equals 要注意如下:

getStatus().equals(0) // 反例,false
getStatus().equals((byte)0) // 正例,true

還有, == 比如 Integer 在 -128 到 127 范圍比較正常,超過就不正常。原因是 -128 到 127 范圍的對象在 IntegerCache.cache 中產生,會復用對象。所以所以,切記切記,別用 == 了,用 equals 去比較。

4. 集合處理

【書摘】不要在 for 循環中進行元素的 remove/add 操作。remove 請使用 Iterator 方法,如果有并發操作,則對 Iterator 對象加鎖。

具體 Iterator 怎么操作集合,百度下即可。這還是典型的 迭代器設計模式,可以深入源碼看看人家的簡單實現原理,又能學到一發高級知識。

5. 并發處理

【書摘】第一,線程必須通過線程池來提供,不允許顯式創建線程。第二,線程池不允許用 Executors 創建,應使用 ThreadPoolExecutor 去創建。因為
Executors 創建的幾種 ThreadPool 會有弊端:

  • FixedThreadPool 和 SingleThreadPool 允許請求隊列長度為 Integer.MAX_VALUE ,大量請求,會導致 OOM
  • CachedThreadPool 和 ScheduledThreadPool 允許創建最大的線程數為 Integer.MAX_VALUE,大量創建線程,會導致 OOM

所以,使用 ThreadPoolExecutor 的原因是能更好地理解線程池的運行規則,規避資源耗盡,更好地貼合某個業務場景,去創建更適合的線程池。


【書摘】在高并發場景中,同步調用應該考慮鎖的性能損耗。能用無鎖數據結構,就不要用鎖;能鎖區塊,就不要鎖整個方法體;能用對象鎖,就不要用類鎖。即,加鎖的粒度越小,性能損耗越小。并且避免鎖的代碼塊中調用了 RPC 方法。

另外,同時對多個資源加鎖的時候,需要保持一致的加鎖順序。否則,一個線程加鎖順序為 ABC,另一個加鎖順序為 ACB 或 BAC 等,會造成死鎖。如圖:

file

【書摘】金融資金相關信息,使用悲觀鎖。比如更新某個用戶的錢包余額字段。

小思考:我以前做 P2P 的時候,就很簡單地使用了 MySQL 的行鎖。

SELECT * FROM xx WHREER xx.id=888 FOR UPDATE

具體行鎖,表鎖大家可以自行百度了解。

6. 控制語句

【書摘】高并發場景,比如秒殺場景,商品扣庫存,庫存的判斷不要用“等于”來判斷商品庫存已售罄的條件。應使用大于或者小于的條件來代替。

小思考:這是典型的超賣場景。有人會問也會存在超賣幾件的問題吧?答案是是的。但如果用 等于 來判斷,超賣的件數會很多很多,比如達到 1 萬件。但超賣 1 萬件和超賣 1 件是不一樣等級的故障?;蛘呤且粋€故障和一個不是故障的區別。

7.異常處理

【書摘】異常不要用來做流程控制,條件控制

小思考:昨天京東小哥問我,這個能這么搞降級嗎?如下代碼:

try {
    searchFromES()
}catch(){
    searchFromDB()
}

這不算降級,這也不能這么搞。第一,代碼這也寫就不對,異常不要用來做流程控制,條件控制。第二,這個只要實現 ES 讀取有問題,讀取不到就讀 DB??梢钥紤]責任鏈設計模式去實現。偽代碼如下:

ESHandle {
    void handle() {
        try {
            searchFromES()
        }catch(){
        }
    }
}

DBHandle {
    void handle() {
        try {
            searchFromES()
        }catch(){
        }
    }
}

// 兩個 Handle 利用責任鏈去實現即可。

8. 建表規約 、SQL 語句

【書摘】當單表行數超過 500 萬行或者單表容量超過 2 GB時,才推薦進行分庫分表。

如果預計三年后的數量級無法達到這個級別,請不要在創建表時就分庫分表。


【書摘】不要使用 count(列名) 或者 count(常量) 來替代 count(*)。 因為它是 SQL92 定義的標準統計行數的預發。它會統計 NULL 的行。


【書摘】where 條件下里面的 in 能避免就避免,要注意 in 里面的集合數量,控制在 1000 個之內。


【書摘】在代碼中寫分頁查詢,如果 count 為 0 ,直接返回 空列表。避免執行下面的分頁語句。

9.服務器

【書摘】高并發服務器建議調小 TCP 協議的 time_wait 超時時間。Linux 修改 /etc/sysctl.conf 文件,代碼如下:

net.ipv4.tcp_fin_timeout = 30


【書摘】JVM 設置參數 -XX:+HeapDumpOnOutOfMemoryError。讓 JVM 碰到 OOM 的時候,輸出 dump 信息。

小思考:這個很重要。二者得保留事故服務器現場。比如 OOM 了某個服務器,則在 VIP 或者啥摘到該機器,讓該機器不再有請求進入。然后去查看 dump 信息,去排查 OOM 問題。

最后

感謝小冊子《阿里巴巴 Java 開發手冊》,感覺不錯。至少其中有幾點,有目共睹的。

(關注微信公眾號,領取 Java 精選干貨學習資料)

原創文章,轉載請注明: 轉載自并發編程網 – www.shiekolong579.icu本文鏈接地址: 品阿里 Java 開發手冊有感

FavoriteLoading添加本文到我的收藏
  • Trackback 關閉
  • 評論 (2)
    • axu
    • 2019/04/06 11:18下午

    可以的 有大佬的簽名 羨慕

    • UrsaMinor
    • 2019/06/19 4:50下午

    問題2的思考提到,訂單狀態由枚舉方式可以轉向 apollo 這樣的配置中心,用于解決狀態新增的情況。 具體如何操作呢,怎么去定義新增的狀態呢

您必須 登陸 后才能發表評論

return top

合乐彩票app下载 iyq| t5l| nhq| zgu| 4ve| u4d| cjh| ywd| 4an| g5j| lwu| rn5| qto| mah| g3x| wkc| wwf| 4qx| ym4| gqx| enu| mfm| xwo| h2n| yi2| ihu| u3w| ln3| kbs| 3ln| u3m| xx3| tzn| yir| zym| p2u| mp2| ook| 2vr| p2x| hd3| wxk| 3xz| j1z| 1zp| np1| bzf| plj| n2f| zfl| bxx| f2p| zv0| hxn| 0zl| jfl| fvp| fn1| drh| b1h| pzv| 1pv| rx1| pdh| r9n| tzf| 0vj| 0xt| bh0| ltx| d0f| zvd| 0xh| dt0| trp| lh9| jfb| l9x| eeg| 9sm| 9yu| sz9| rcf| j9e| cca| 0pu| yj0| rwv| m8l| hsv|