zoukankan      html  css  js  c++  java
  • Java开发手册精华总结

    阿里 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 等,会造成死锁。如图:

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

    工程师对于代码,一定要精益求精,不论从性能,还是简洁优雅,都要具备精益求精的工匠精神,认真打磨自己的作品。
    -- 多隆

    本文由博客群发一文多发等运营工具平台 OpenWrite 发布

  • 相关阅读:
    C#
    C#
    ssh学习笔记
    (已解决)Could not open '/var/lib/nova/mnt/*/volume-*': Permission denied
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    如何在linux下安装idea
    The system has no LUN copy license
    调整mysql数据库最大连接数
    mysql数据库编码问题
    cinder支持nfs快照
  • 原文地址:https://www.cnblogs.com/Alandre/p/13772643.html
Copyright © 2011-2022 走看看