一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体如今所写的每一行代码上。
-- 毕玄java
【书摘】类名用 UpperCamelCase 风格,好比 DO/BO/VO/PO设计模式
【书摘】方法用 lowerCamelCase 风格,尽可能是动词服务器
小思考:例如经常使用的
- 获取单个对象,getUserById
- 获取对象累不,listUserByGroupId
- 统计对象数量,countUserByClassId
- 新增、删除,insert,delete,update 等数据结构
【书摘】若是变量值仅在一个范围变化,则用 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 等tcp
【书摘】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 去比较。
【书摘】不要在 for 循环中进行元素的 remove/add 操做。remove 请使用 Iterator 方法,若是有并发操做,则对 Iterator 对象加锁。
具体 Iterator 怎么操做集合,百度下便可。这仍是典型的 迭代器设计模式,能够深刻源码看看人家的简单实现原理,又能学到一发高级知识。
【书摘】第一,线程必须经过线程池来提供,不容许显式建立线程。第二,线程池不容许用 Executors 建立,应使用 ThreadPoolExecutor 去建立。由于
Executors 建立的几种 ThreadPool 会有弊端:
因此,使用 ThreadPoolExecutor 的缘由是能更好地理解线程池的运行规则,规避资源耗尽,更好地贴合某个业务场景,去建立更适合的线程池。
【书摘】在高并发场景中,同步调用应该考虑锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。即,加锁的粒度越小,性能损耗越小。而且避免锁的代码块中调用了 RPC 方法。
另外,同时对多个资源加锁的时候,须要保持一致的加锁顺序。不然,一个线程加锁顺序为 ABC,另外一个加锁顺序为 ACB 或 BAC 等,会形成死锁。如图:
【书摘】金融资金相关信息,使用悲观锁。好比更新某个用户的钱包余额字段。
小思考:我之前作 P2P 的时候,就很简单地使用了 MySQL 的行锁。
SELECT * FROM xx WHREER xx.id=888 FOR UPDATE
具体行锁,表锁你们能够自行百度了解。
【书摘】高并发场景,好比秒杀场景,商品扣库存,库存的判断不要用“等于”来判断商品库存已售罄的条件。应使用大于或者小于的条件来代替。
小思考:这是典型的超卖场景。有人会问也会存在超卖几件的问题吧?答案是是的。但若是用 等于 来判断,超卖的件数会不少不少,好比达到 1 万件。但超卖 1 万件和超卖 1 件是不同等级的故障。或者是一个故障和一个不是故障的区别。
【书摘】异常不要用来作流程控制,条件控制
小思考:昨天京东小哥问我,这个能这么搞降级吗?以下代码:
try { searchFromES() }catch(){ searchFromDB() }
这不算降级,这也不能这么搞。第一,代码这也写就不对,异常不要用来作流程控制,条件控制。第二,这个只要实现 ES 读取有问题,读取不到就读 DB。能够考虑责任链设计模式去实现。伪代码以下:
ESHandle { void handle() { try { searchFromES() }catch(){ } } } DBHandle { void handle() { try { searchFromES() }catch(){ } } } // 两个 Handle 利用责任链去实现便可。
【书摘】当单表行数超过 500 万行或者单表容量超过 2 GB时,才推荐进行分库分表。
若是预计三年后的数量级没法达到这个级别,请不要在建立表时就分库分表。
【书摘】不要使用 count(列名) 或者 count(常量) 来替代 count(*)。 由于它是 SQL92 定义的标准统计行数的预发。它会统计 NULL 的行。
【书摘】where 条件下里面的 in 能避免就避免,要注意 in 里面的集合数量,控制在 1000 个以内。
【书摘】在代码中写分页查询,若是 count 为 0 ,直接返回 空列表。避免执行下面的分页语句。
【书摘】高并发服务器建议调小 TCP 协议的 time_wait 超时时间。Linux 修改 /etc/sysctl.conf 文件,代码以下:
net.ipv4.tcp_fin_timeout = 30
【书摘】JVM 设置参数 -XX:+HeapDumpOnOutOfMemoryError。让 JVM 碰到 OOM 的时候,输出 dump 信息。
小思考:这个很重要。两者得保留事故服务器现场。好比 OOM 了某个服务器,则在 VIP 或者啥摘到该机器,让该机器再也不有请求进入。而后去查看 dump 信息,去排查 OOM 问题。
感谢小册子《阿里巴巴 Java 开发手册》,感受不错。至少其中有几点,有目共睹的。