摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢!

一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。
-- 毕玄

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 问题。

最后

感谢小册子《阿里巴巴 Java 开发手册》,感觉不错。至少其中有几点,有目共睹的。

 
(关注微信公众号,领取 Java 精选干货学习资料)

品阿里 Java 开发手册有感的更多相关文章

  1. 阿里JAVA开发手册零度的思考理解(一)

    转载请注明原创出处,谢谢! 缘由 阿里JAVA开发手册已经发表有很长时间了,值得认真研究思考推广 阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的哲学,值得好 ...

  2. 阿里JAVA开发手册零度的思考理解(二)

    转载请注明原创出处,谢谢! 说在前面 人生的大道上默默地走,就必须要有一盏灯亮着为你引导方向!而这盏灯抑或只是一句话,一句鼓励,一个赞美,一次承认,一次认可,一次相识一次交流-- 上篇文章:阿里JAV ...

  3. 阅读阿里Java开发手册记录

    概述 在阅读完阿里Java开发手册(嵩山版)后,发现自己在开发过程中有一些没有按照规范开发的情况,这里将容易忘记的规范记录下来,并且添加自己的理解,一方面方便自己巩固记忆,另一方面希望对其他同学能够提 ...

  4. JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法

    前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式, 这样的处理方式让写的同学 ...

  5. 从阿里Java开发手册学习线程池的正确创建方法

    前言 最近看阿里的 Java开发手册,上面有线程池的一个建议: [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更 ...

  6. 【转】线程池体系介绍及从阿里Java开发手册学习线程池的正确创建方法

    jdk1.7中java.util.concurrent.Executor线程池体系介绍 java.util.concurrent.Executor : 负责线程的使用与调度的根接口  |–Execut ...

  7. 阿里java开发手册中命名规约解读之DO/BO/DTO/VO/AO

    前言 在阅读<阿里巴巴Java开发手册>时,看到命名规则中有这样一条 虽然知道这些是根据Java对象的角色所分配名称的后缀,但是没有弄清楚分别是什么意思,日常开发中也没有使用到. 网上查找 ...

  8. 读《阿里Java开发手册》总结(1)

    一·命名约定 类名使用大驼峰式命名(领域模式相关命名除外:如DAO\VO\DO等). 常量必须全部大写,单词中间用“_”隔开(如MAX_COUNT). 抽象类命名使用Abstract或Base开头.异 ...

  9. 阿里Java开发手册1.3.0 文字版

    版本: 1.3.0 update: 2017.9.25 一.编程规约 (一) 命名风格 1. [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:_name _na ...

随机推荐

  1. MFC中listbox控件中各种属性的详解

     ListBox控件是Windows 窗体的一个空间,ListBox 控件显示一个项列表,用户可从中选择一项或多项.      如果项总数超出可以显示的项数,则自动向 ListBox 控件添加滚动条. ...

  2. 在vs中编写代码常用的快捷键

    作为一个程序员,能够熟悉使用各种快捷键,可以增加我们编写和调试代码的速度,下面我就对常使用的快捷键做一些总结,下面这些快捷键基本适用于所有版本的vs: 最给力: Ctrl+K+F   快速整理代码格式 ...

  3. 【prufer编码+组合数学】BZOJ1005 [HNOI2008]明明的烦恼

    Description 自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Solution 这 ...

  4. [Poi2014]FarmCraft 树状dp

    对于每个点,处理出走完其子树所需要的时间和其子树完全下载完软件的时间 易证,对于每个点的所有子节点,一定优先选择差值大的来给后面的时间 树规+贪心. #include<cstdio> #i ...

  5. SAP S4系统创建Customer和Vendor的BAPI

    对应的BAPI是:RFC_CVI_EI_INBOUND_MAIN SAP 又调皮了,又不安常理出牌!

  6. jquery中attr()和prop()的区别

    最近项目回归使用jquery,页面渲染全是使用jquery做的,所以做的时候也遇到了许多以前没有见过的问题,如这次操作[radio]控件的"checked"属性时有遇到问题, $( ...

  7. java泛型中使用的排序算法——归并排序及分析

    一.引言 我们知道,java中泛型排序使用归并排序或TimSort.归并排序以O(NlogN)最坏时间运行,下面我们分析归并排序过程及分析证明时间复杂度:也会简述为什么java选择归并排序作为泛型的排 ...

  8. 【转】百度站长平台MIP引入工具使用心得

    MIP引入主动推送流程 对于 MIP 站点改造好了,我们如何提交数据,并且 MIP 提交后,我们能得到哪些数据的反馈,在这里简单的写一篇文章,说一下. 改造 MIP,我们一般是添加了一个二级域名站点进 ...

  9. JS 图片放大镜

    今天练习一个小demo, 从本地读取图片, 然后实现类似淘宝放大镜的效果, 再加两个需求 1 .可以调节缩放比例,默认放大两倍 2 . 图片宽高自适应, 不固定宽高 话不多说先看效果: 原理:1, 右 ...

  10. Java GC性能优化实战

    GC优化是必要的吗? 或者更准确地说,GC优化对Java基础服务来说是必要的吗?答案是否定的,事实上GC优化对Java基础服务来说在有些场合是可以省去的,但前提是这些正在运行的Java系统,必须包含以 ...