共计 2917 个字符,预计需要花费 8 分钟才能阅读完成。
阿里 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 公布