阿里 Java 開發手冊的思考總結
一個優秀的工程師和一個普通的工程師的區別,不是滿天飛的架構圖,他的功底體現在所寫的每一行代碼上,
-- 畢玄
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 等,會造成死鎖,如圖:

【書摘】金融資金相關資訊,使用悲觀鎖,比如更新某個用戶的錢包余額欄位,
小思考:我以前做 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 問題,
工程師對于代碼,一定要精益求精,不論從性能,還是簡潔優雅,都要具備精益求精的工匠精神,認真打磨自己的作品,
-- 多隆
本文由博客群發一文多發等運營工具平臺 OpenWrite 發布
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/159284.html
標籤:其他
上一篇:一分鐘帶你讀懂什么是堆?
下一篇:計算機網路之第1章 概念
