精华内容
下载资源
问答
  • 注:本文内容整理自《阿里java编码规范》+《代码整洁之道》 代码规范的重点在于保持代码可读性和团队协作的一致性,并不是说不遵守规范代码就无法运行。让代码可读、优雅、漂亮,是一件让自己舒服也让其他读代码的...

    注:本文内容整理自《阿里java编码规范》+《代码整洁之道》

    代码规范的重点在于保持代码可读性团队协作的一致性,并不是说不遵守规范代码就无法运行。让代码可读、优雅、漂亮,是一件让自己舒服也让其他读代码的人更加舒服的事情。

    本文讲的是传统意义上的代码规范,包括变量命名、代码风格、控制语句、 代码注释等基本的编程习惯,以及从高并发场景中提炼出来的集合处理技巧与并发多线程的注意事项。

    命名风格

    强制

    1、任何名称都不要以下划线、美元符号或者其他特殊符号来开头或者结束。尽可能不要使用特殊符号(常量的下划线除外)。

    2、严禁使用汉语拼音或者拼音+英文的命名方式,但是alibaba/taobao/youku/hangzhou等国际通用的名称,可视作英文。

    3、类名和接口名使用大驼峰;方法名、参数名、成员变量名、局部变量名使用小驼峰;常量命名使用全大写,如果需要使用下划线分隔,力求语意表达出来,不要嫌长。

    4、抽象类命名使用Abstract或者Base开头;异常类命名使用Exception结尾;测试类命名要以它要测试的类名开头,以Test结尾。

    5、定义数组使用int[] name中括号紧跟类型的方式。

    6、POJO类(实体类)中的布尔型变量不要加is前缀,否则部分框架解析会引起序列化错误。假设变量名是isDeleted,那么生成的方法也是isDeleted,有些框架在反向解析时,由于要获取属性名称,会误以为是deleted,导致属性获取不到而出现异常。

    7、包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词,且包名统一使用单数形式比如com.alibaba.ai.util,但是注意,如果类名具有复数含义,可以使用复数形式,比如MessageUtils。

    8、杜绝不规范的缩写,比如AbstractClass缩写成AbsClass,condition缩写成condi,此类随意的缩写严重降低了代码的可读性。

    9、对于Service和Dao类,内部的实现类使用Impl后缀。

    推荐

    1、尽可能使用完整的可自解释的英文单词来命名,不要怕太长,比如在JDK中就有AtomicReferenceFieldUpdater,绝对要避免随意的命名比如a/b/kk等。

    2、接口中的属性和方法不要加任何的修饰符,保持代码的简洁性。并提供Javadoc文档注释。另外尽量不要在接口中定义任何变量,如果一定要定义,则必须是和接口相关的,并且是整个应用的基础常量。

    3、类名和属性名等一般使用名词或者名词短语;方法名一般使用动词或者动词+名词;属性访问器、修改器和断言应该根据其值命名,并依次加上get、set和is前缀。

    参考

    1、枚举类以Enum为后缀,并且枚举类的常量使用全大写+下划线的命名方式。

    2、获取单个对象的方法用get做前缀;获取多个对象的方法使用list做前缀;获取统计值的方法使用count做前缀;插入的方法使用save/insert做前缀;删除的方法使用remove/delete做前缀;修改的方法使用update做前缀。


    常量定义

    强制

    1、不允许任何魔法数字直接出现在代码中。

    2、long或者Long类型的变量在赋值时,后面要加上大写的L。

    推荐

    1、不要使用一个常量类来维护所有的常量,要按照功能进行分类,分开维护。比如缓存相关的常量放在类CacheConsts下,系统配置相关的常量放在类ConfigConsts下。

    2、常量的复用层次共有5层。跨应用共享常量要放置在二方库中,通常是client.jar的constant目录下;应用内共享常量要放置在一方库中,通常是子模块的constant目录下;子工程内部共享常量放在子工程的constant目录下;包内共享常量放在当前包下单独的constant目录下;类内共享常量直接放在类内部private static final定义。


    代码格式

    强制

    1、大括号的使用约定:如果大括号内为空,则简洁地写成{ }即可,不需要换行;如果是非空代码,则左大括号前不换行,左大括号后换行,右大括号前换行,右大括号后还有else等代码则不换行,表示终止的右大括号必须换行。

    2、小括号内部两端和字符之间不要隔空,比如 (a + b),不要( a + b )。

    3、if/for/while/do/switch等保留字与括号之间要有一个空格。

    4、任何二目、三目运算符的左右两边都需要加一个空格。

    5、采用4个空格缩进,禁止使用Tab控制符。

    6、注释的双斜线与注释内容之间有且仅有一个空格。

    7、单行字符数不能超过120个,超出则需要换行,换行时遵循如下规则:第二行相对第一行缩进4个空格,从第三行开始不再持续缩进;运算符和下文一起换行;方法调用的点符号与下文一起换行;方法调用中的多个参数需要换行时,在逗号后进行;在括号前不要换行;在逗号前不要换行。

    8、方法参数的定义和传入时,多个参数逗号后边必须加空格,比如("a", "b")。

    推荐

    1、没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。

    2、不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开,以提升可读性,没有必要插入多个空行。


    OOP规约

    强制

    1、避免通过一个类的对象引用静态变量或者静态方法,无谓增加编译器的解析成本,直接使用类名来访问即可。

    2、所有复写的子类方法都必须要加@Override注解。

    3、尽量不用可变参数编程。

    4、不能使用过时的类和方法。

    5、对外部正在调用或者二方库依赖的接口,不允许修改方法签名,以避免对接口调用方产生影响。若接口过时, 必须加©Deprecated注解,并清晰地说明釆用的新接口或者新服务是什么。

    6、使用euqals方法时,应使用常量或者确定有值的对象来调用。推荐使用工具类来进行比较。

    7、关于基本数据类型和包装类数据类型的使用选择:所有的POJO类属性必须使用包装数据类型(和数据库更好地兼容);RPC方法(远程调用方法)的参数和返回值必须使用包装类型;所有的局部变量都要使用基本数据类型;集合中使用包装类型;如果都能用的地方则优先使用基本数据类型。

    8、构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

    9、实体类必须重写toString方法,如果继承了另一个实体类,记得在前面加上super.toString。

    10、当使用索引访问用String的split方法得到的 数组时,需在最后一个分隔符后做有无内容的检查,否则会有抛 IndexOutOfBoundsException 的风险。

    推荐

    1、当一个类有多个构造方法,或者多个同名方法时, 这些方法应该按顺序放置在一起,便于阅读,此规则优先于下一条规则。

    2、类内方法定义的顺序是:公有方法或保护方法 > 私 有方法> getter / setter方法。

    3、在setter方法中,参数名称与类成员变量名称一 致,this.成员名=参数名。在getter / setter方法 中,不要增加业务逻辑,否则会增加排查问题的难度。(使用自动生成的即可)

    4、在循环体类,字符串的拼接使用缓冲类StringBuilder的append方法。

    5、慎用Object的clone方法来拷贝对象。


    集合处理

    1、关于hashCode和equals的处理,遵循如下规则:只要重写equals,就必须重写hashCodeo;因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两种方法;如果自定义对象作为Map的键,那么必须重写hashCode 和equals。说明:String重写了 hashCode和equals方法,所以我们可以非常愉快地将String对象作为key来使用。

    2、使用集合转数组的方法,必须使用集合的 toArray (T[] array),传入的是类型完全一样的数组, 大小就是list .size ()。

    3、在使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove /clear方法会抛出 UnsupportedOperationException异常。

    4、不要在foreach循环里进行元素的remove操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。

    推荐

    1、集合初始化时指定集合大小。

    6、使用entrySet遍历Map类集合K/V,而不是用keyset方式遍历。


    控制语句

    强制

    1、在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。

    2、在if/else/for/while/do语句中,必须使用大括号。即使只有一行代码,也应避免釆用单行的编码方式:if (condition) statements;

    推荐

    1、在表达异常的分支时,尽量少用if-else方式,可以使用卫语句来替代。

    2、不要在条件 判断中执行其他复杂的语句,可将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

    3、循环体中的语句要考量性能。以下操作尽量移至循环体外处理,如定义对象或变量、获取数据库连接,避免进行不必要的try-catch操作。 说明:对循环体内的try-catch操作,需要思考是否可以移至循环体外。

    4、避免采用取反逻辑运算符


    注释规范

    强制

    1、类、类属性、类方法的注释必须使用Javadoc规范, 使用/**内容**/格式,不得使用// xxx方式。 

    2、所有的抽象方法(包括接口中的方法)必须要用 Javadoc注释,除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。说明:对子类的实现要求,或者调用注意事项,请一并说明。

    3、所有的类都必须添加创建者和创建日期。

    4、方法内部的单行注释,在被注释语句上方另起一行, 使用//注释。方法内部的多行注释,使用/* */注释,注意与代码对齐。

    5、所有的枚举类型字段必须要有注释,说明每个数据项的用途。

    推荐

    1、与其用“半吊子”英文来注释,不如用中文注释把 问题说清楚。专有名词与关键字保持英文原文即可。

    2、在修改代码的同时,要对注释进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。

    参考

    1、谨慎注释掉代码。要在上方详细说明,而不是简单地注释掉。如果无用,则删除。说明:代码被注释掉有两种可能性。 1)后续会恢复此段代码逻辑。 2)永久不用。 前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库中保存了历史代码)。

    2、对于注释的要求: 1)能够准确反映设计思想和代码逻辑。 2)能够描述业务含义,使其他程序员能够迅速了解代码背后的信息。完全没有注释的大段代码对于阅读者形同天书;注释是给自己看的,应做到即使间隔很长时间,也能清晰理解当时的思路;注释也是给继任者看的,使其能够快速接替自己的工作。

    3、好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的一个极端:过多过滥的注释,因为代码的逻辑一旦修改,修改注释是相当大的负担。

    4、特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描经常清理此类标记。有时候线上故障就来源于这些标记处的代码。待办事宜(TODO):(标记人,标记时间,[预计处理时间])表示需要实现,但目前还未实现的功能。这实际上是一个Javadoc的标签,虽然目前的Javadoc还没有实现,但已经被广泛使用,且只能应用于类、接口和方法(因为它是一个Javadoc标签);2)错误,不能工作(FIXME):(标记人,标记时间,[预计处理时间])在注释中用FIXME标记某代码是错误的, 而且不能工作,需要及时纠正。


    补充:《代码整洁之道》

    命名

    1、命名应能体现该名称在业务逻辑中所表示的含义。

    2、命名应避免误导性,比如使用字母O和数字0,字母l和数字1,以及其他难以区分的名称如userName和useName,或者具有特殊含义的缩写等。

    3、命名应做有意义的区分,比如Product、ProductInfo、ProductData这几个名称,有区别吗?难以区分,这时的后缀Info或者Data等都是意义含混的废话。

    4、在一个工程中,命名习惯应一以贯之。

    方法

    1、函数应当短小,只做好一件事,对于这“一件事”的理解,重点在于不要将封装和细节过多地杂糅在一起。可以就业务逻辑【自顶向下按照【抽象层次】依次布局,直到最后的细节实现。

    2、如果一个方法中的细节还足够再拆出一个方法,那么就可以将这些细节进行封装,然后再调用。

    3、别害怕长名称,长并且有描述性的名称,要比短而令人费解的名称好。

    4、方法的参数不要超过5个,最理想的数量是零,常见的是一二三个。(注意,参数与函数名处于不同的抽象层级,它要求你了解目前并不特别重要的细节)。

    5、如果函数看来需要两个、三个或三个以上参数,就说明其中一些参数应该封装为类了。

    6、方法应该没有副作用,即如果某个方法名为checkPassword,可是在代码中除了检查密码还做了其他的事情,这时,这些其他的事情就隐藏在该方法之中,而对外并不知道,就很容易因为这种副作用而出现问题。

    7、函数要么做什么事,要么回答什么事,即函数应该修改某对象的状态或是返回该对象的有关信息。两样都干常常会导致混乱。

    8、如果方法可能会出现异常,则使用异常处理机制进行处理。使用异常处理来替代错误码。

    9、千万不要重复代码。千万不要重复代码。千万不要重复代码。代码可复用是一项十分重要的原则。

    10、和写文章一样,先写初稿,然后打磨。

    11、不要返回null值(也不要传递null值),因为null会引起空指针异常,如果总是返回null,则需要做大量的空指针检验。

    展开全文
  • 如果我们在多线程中引入了共享变量,那么我们就需要考虑一下多线程下线程安全的问题了。那么我们在编写代码的过程中,需要注意哪些线程安全的问题呢?一起来看看吧。大家都做过方法重写,我们知道方法重写是不会检查...
  • java性能编码规范整理二

    千次阅读 2012-06-14 23:57:37
    接上篇 java性能编码规范整理一 12、对于高频度使用的对象,需要进行单独优化处理给以重用13、在代码开发中,需要根据应用场景合理选择集合框架中的集合类,应用场景可按单线程和多线程来划分,也可按频繁插入、...
    12、对于高频度使用的对象,需要进行单独优化处理给以重用
    13、在代码开发中,需要根据应用场景合理选择集合框架中的集合类,应用场景可按单线程和多线程来划分,也可按频繁插入、随机提取等具体操作场景来划分
    14、对于热点代码,可以采用特定的集合类来提供系统性能,特定集合类可以是自己开发,也可以直接采用Trove这样的第三方开源类库
    15、当需要在方法之间传递多个属性值时,从性能角度考虑,应优先采用结构体,而非ArrayList或Vector等集合类
    16、进行IO读写操作时,必须使用缓冲机制
    17、从性能角度考虑,应尽量优先使用字节IO进行读写,而避免用字符IO进行读写
    18、对于数组、集合的拷贝、查找、排序等操作,如果是一般应用,可以优先采用java.util.Arrays和java.util.Collections中提供的工具方法;但是对于热点代码,最好是参考java API中的方法实现,自己开发特定的排序等方法,以减少临时对象的创建。
    19、对于数组的拷贝,请使用System.arraycopy(…)方法
    20、如果往框架类或者系统类对象中添加了某个对象,那么当该对象不再使用时,必须及时清除
    21、当使用自己定义的类装载器去装载类时,在被装载的类不再使用后,需要保证该类装载器可以被垃圾回收
    22、尽量不要将一些大的对象(对象本身比较大或其引用的对象比较多)定义成静态的
    23、如果在一个对象中创建了一个线程,当对象不再使用时,必须关闭该线程
    24、在JFrame、JDialog等窗口对象中,尽量处理窗口关闭事件并释放资源
    25、在IO操作中,必须定义finally代码段,并在该代码段中执行IO关闭操作

    <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
    展开全文
  • getmestage推荐使用ScheduledExecutorService方式处理Timer运行个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行ScheduledExecutorService并发运行个定时任务时,其中某线程抛出异常,...

    getmestage

    推荐使用ScheduledExecutorService方式处理

    Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行

    ScheduledExecutorService并发运行多个定时任务时,其中某线程抛出异常,不会影响到其它线程的继续运行

    表名、字段名禁止出现数字开头,禁止两个下划线中间只出现数字

    表名不使用复数名词

    表必备三字段命名:id, gmt_create, gmt_modified

    TreeMap的key不可以为null

    注释:HashMap的key/value均可以为null,但是TreeMap的key不能为空,value可以为空

    mvn dependency:resolve 打印出已仲裁依赖的列表

    mvn dependency:tree 打印工程整个的依赖树结构

    mvn dependency:tree -Dverbose -Dincludes=commons-lang 打印出与commons-lang相关的详细依赖

    Long a=2L;//大写的L

    不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护

    SimpleDateFormat 是线程不安全的类

    一般不要定义SimpleDateFormat的static变量,如果定义为static,必须保证线程安全

    推荐使用Apache封装好的DateUtils和DateFormatUtils工具类,来处理时间日期转换问题

    代码块缩进4个空格,如果使用tab缩进,请设置成1个tab为4个空格

    方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间推荐插入一个空行

    相同业务逻辑和语义之间不需要插入空行

    数组元素的修改,会影响到转化过来的集合

    对于转换过来的集合,它的 add/remove/clear 方法会抛出: UnsupportedOperationException

    .Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组

    方法签名中,抛给调用者的关键字为throws

    .自定义异常要做到“认知对等”,即:抛出者和接收者要保持对自定义异常的认知统一,接收方需要知道这种异常的含义和对应的处理方案

    Hashtable的KV都不可以为null

    HashMap的KV都可以为null

    ConcurrentHashMap的KV都不可以为null

    语句覆盖度是最弱的覆盖度量方式

    checked异常继承java.lang.Exception类

    unchecked异常继承java.lang.RuntimeException类

    NullPointerException , IllegalArgumentException属于unchecked exception

    类名使用UpperCamelCase,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / DTO / VO / DAO等

    抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾

    枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开

    如果使用到了设计模式,建议在类名中体现出具体模式。例如代理模式的类命名:LoginProxy;观察者模式命名:ResourceObserver

    主键查询优先于二级索引查询

    表连接有一定的代价,故表连接数量越少越好

    一般情况下,二级索引扫描优先于全表扫描

    可以使用通过索引避免排序代价

    异常信息应该包括两类信息:案发现场信息和异常堆栈信息

    日志文件推荐至少保存15天,因为有些异常具备以“周”为频次发生的特点

    避免重复打印日志,浪费磁盘空间,务必在log4j.xml中设置additivity=false

    错误日志和业务日志尽量分开存放

    查询语句WHERE date_format(gmt_create, ‘%Y-%m-%d’) = '2016-11-11’无法利用gmt_create索引

    当 c 列类型为 char 时,查询语句 WHERE c = 5 无法利用c索引

    索引字段使用时不能进行函数运算

    对varchar类型的字段建立索引,必须指定索引长度

    业务上具有唯一特性的字段(含组合字段),必须指定唯一索引

    建复合索引时,一般选择区分度高的字段放在最左列

    对于Service类,内部的实现类加Impl的后缀与接口区别。例如:ProductServiceImpl实现ProductService接口

    对于Service类,基于SOA的理念,是以接口方式暴露服务

    尽量不在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,而且是整个应用的基础常量

    POJO类的serialVersionUID不一致会抛出序列化运行时异常

    向公司外部提供的http/api接口,推荐使用“错误码”方式返回异常或者错误信息。

    对于应用内部的方法调用,推荐使用“抛出异常”的方式处理异常或者错误信息

    跨应用的RPC调用,推荐使用将“错误码”和“错误简短信息”封装成Result的方式进行返回

    对外提供的接口,一定要保证逻辑健壮性:尽量避免空指针等技术类异常;对于业务类异常要做好错误码或者异常信息的封装

    订单详情页面

    类目管理后台

    店铺装修后台

    订单付款页面

    分页查询,当统计的count为0时,应该直接返回,不要再执行分页查询语句

    iBATIS自带的queryForList(String statementName,int start,int size)分页接口有性能隐患,不允许使用

    定义明确的sql查询语句,通过传入参数start和size来实现分页逻辑

    有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回滚事务

    所有的覆写方法,必须是强制加 @Override

    setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名

    在getter方法中,尽量不要增加逻辑判断,因为添加了逻辑判断后,会增加排查问题难度

    使用synchronized关键字给对象的读写操作加锁

    如果是基本类型,推荐使用java.util.concurrent.atomic包下面提供的线程安全的基本类型包装类,例如AtomicInteger

    如果是集合,推荐使用java.util.concurrent提供的并发集合类,例如:ConcurrentHashMap

    运算符与下文一起换行,方法调用的点符号与下文一起换行。  .append()

    在多个参数超长,逗号后进行换行

    在括号前不要换行

    SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好

    sql查询条件 where a like ‘%阿里%’ ,不会走索引

    sql查询条件 where a like ‘阿里%’ ,a列创建了索引,一般会使用索引进行检索

    能够减少在创建和销毁线程上所花的时间以及系统资源的开销

    线程资源必须通过线程池提供,不允许在应用中自行显式创建线程

    日志尽量记录案发现场信息和异常堆栈信息

    如果日志中输出POJO类,POJO类需要重写toString方法,避免只输出hashCode

    使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行至 await 方法,直到超时才返回结果

    子线程抛出异常堆栈,不能在主线程 try-catch 到

    Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组

    数据库中,表达是与否概念的字段,必须使用is_xxx的方式命名

    不要用resultClass当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义

    类定义开始部分,一般都用Javadoc注释 程序的总体描述以及作者信息

    方法头定义签名上的注释必须遵守javadoc规范,使用/**回车来生成,不得在方法定义上方使用//(双划线)简单说明

    常量命名应该全部大写,单词间用下划线隔开

    常量的定义要力求语义表达完整清楚,让别人能从常量名称上大致了解含义,例如:MAX_STOCK_COUNT

    在使用缩写时要注意:杜绝不规范的缩写

    二方库里可以定义

    二方库里接口的入参可以使用枚举类型

    二方库里接口的返回值是枚举类型或包含枚举类型时,当二方库的枚举值升级(增加枚举值)时,可能会导致接口调用时出现枚举对象序列化异常

    hashcode决定(如:HashMap)存储位置;equals决定是否需要覆盖(同一hash下)集合元素

    类重写hashcode,必须重写equals

    equals 为true,hashcode值相同,但是hashcode值相同,equals可能为false

    跨应用共享常量:放置在二方库中,通常是client.jar中的const目录下

    应用内共享常量:通常放置在一方库的子模块中的const目录下

    子工程内部共享常量:即在当前子工程的const目录下

    类内常量:直接在类内部private static final定义

    当大量socket处于time_wait状态时,会导致可用socket资源稀缺,从而导致服务器并发能力下降

    通过修改/etc/sysctl.conf配置文件,减小time_wait的超时时间,可以降低time_wait状态的socket数量,从而提升服务器并发能力

    捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类

    对大段代码进行try-catch,这是不负责任的表现,分清稳定代码和非稳定代码,对非稳定的代码做对应的异常处理

    可以只锁代码区块的情况下,就不要锁整个方法体

    高并发的业务场景下,要考虑加锁及同步处理带来的性能损耗,能用无锁数据结构,就不要用锁

    能用对象锁的情况下,就不要用类锁

    加锁时需要保持一致的加锁顺序,否则可能会造成死锁

    表单、AJAX提交必须执行CSRF安全过滤

    URL外部重定向传入的目标地址必须执行白名单过滤

    用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定,防止SQL注入,禁止字符串拼接SQL访问数据库

    使用事务回滚的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等

    应用服务器与数据库之间是短连接

    运算符与下文一起换行,方法调用的点符号与下文一起换行

    依赖于一个二方库群时,必须定义一个统一版本变量,避免各子二方库版本号不一致

    所有pom文件中的依赖声明放在语句块中,所有版本仲裁放在语句块中

    线上应用不要依赖SNAPSHOT版本(安全包除外)

    sort表示元素在存入集合时进行了排序,数据遍历的结果是按某个排序规则输出的;而order表示每次遍历的序列都是一样的,元素前后关系每次遍历都是确定的,那么下列TreeSet集合既是sort,又是order的:

    json操作使用fastjson

    md5操作使用commons-codec

    CollectionUtils优先使用org.apache.commons.collections4包

    向公司外部提供的http/api接口,推荐使用“错误码”方式返回异常或者错误信息

    类名使用UpperCamelCase命名法,但是领域模型命名除外,如:ProductDO的命名是规范的

    方法名命名应该使用lowerCamelCase命名法,如方法名:getHttpMessage() 是符合命名规范的

    所有编程相关的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束

    查询语句 where a between 5 and 10 可以使用该索引

    查询语句 where a = 5 and b between 5 and 10 可以使用该索引

    查询语句 where a in (5, 6, 7, 8, 9) and b = 5 可以使用该索引

    表的必备字段:id\gmt_modified\gmt_create

    单元测试代码写在src/test/java目录下

    Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等

    Correct,正确的输入,并得到预期的结果

    Design,与设计文档相结合,来编写单元测试

    数据对象命名:xxxDO,xxx即为数据表名,例如:ResellerAccountDO

    数据传输对象:xxxDTO,xxx为业务领域相关的名称,例如ProductDTO

    展示层对象:xxxVO,xxx一般为网页名称,例如RecommendProductVO

    方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间推荐插入一个空行;相同业务逻辑和语义之间不需要插入空行

    客户的密码,密钥及密保问题答案等信息禁止展示

    客户的银行卡号只显示后四位

    客户的证件号码只显示第一位和最后一位,在必要业务场景下,经多因子强验证后可完整展示

    涉及有完整展示客户信息的页面均需要接入防爬系统

    测试数据入库时加特殊前缀标识

    测试数据使用独立的测试库

    自动回滚单元测试产生的脏数据

    同步处理时,能锁部分代码区块的情况下不要锁整个方法;高并发时,同步调用应该考虑到性能损耗

    创建线程或线程池时,推荐给线程指定一个有意义的名称,方便出错时回溯

    对于“明确停止使用的代码和配置”,如方法、变量、类、配置文件、动态配置属性等要坚决从程序中清理出去,避免造成过多垃圾

    对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码上方,统一规定使用三 个斜杠(///)来说明注释掉代码的理由

    不要在视图模板中加入任何复杂的逻辑

    NULL与任何值的比较结果都为NULL

    当某一列的值全是NULL时,sum(col)的返回结果为NULL

    使用Iterator方式,如果有并发,需要对Iterator对象加锁

    所有的POJO类属性必须使用包装数据类型

    RPC方法的返回值和参数必须使用包装数据类型

    所有的局部变量推荐使用基本数据类型

    版本号命名格式:主版本号.次版本号.修订号

    主版本号:产品方向改变,或者大规模API不兼容,或者架构不兼容升级

    次版本号:保持相对兼容性,增加主要功能特性,影响范围极小的API不兼容修改

    修订号:保持完全兼容性,修复BUG、新增次要功能特性等

    查询语句WHERE date_format(gmt_create, '%Y-%m-%d') = '2016-11-11'无法利用gmt_create索引

    当 c 列类型为 charchar 时,查询语句 WHERE c = 5 无法利用c索引

    特殊注明标记人与标记时间

    待办事宜(TODO):( [标记人,标记时间,[预计处理时间])

    在注释中用FIXME标记某代码是错误的,而且不能工作,需要及时纠正的情况

    若查询条件中不包含索引的最左列,则无法使用索引

    对于范围查询,只能利用索引的最左列

    对于order by A或group by A语句,在A上建立索引,可以避免排序

    对于多列排序,需要所有所有列排序方向一致,才能利用索引

    抽象类命名使用Abstract或Base开头

    异常类命名使用Exception结尾

    测试类命名以它要测试的类的名称开始,以Test结尾

    绝对禁止左模糊

    绝对禁止全模糊

    全模糊或左模糊查询需求,优先使用搜索引擎

    所有的抽象方法(包括接口中的方法)必须要用javadoc注释

    过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担

    我的命名和代码结构非常好,可以减少注释的内容

    Map类型集合推荐使用entrySet进行遍历

    POJO类中的任何布尔类型的变量,都不要加is,因为部分框架解析时有可能会出现序列化错误

    包名统一使用单数形式,如:com.alibaba.mpp.util

    中括号是数组类型的一部分,数组定义如下:String[] args; 不要误写为String args[]

    Service/DAO层方法命名可以参考规约,例如:删除的方法推荐使用remove或delete做前缀

    不允许出现任何魔法值(即未经预先定义的常量)直接出现在代码中

    如果变量值仅在一个范围内变化推荐用Enum类

    在中指定版本号

    避免在不同的子项目,声明同一个二方库的不同版本号

    升级二方库需要比对仲裁结果的差异,谨慎评估

    表字段注释,如果修改字段含义或对字段表示的状态追加时,需要及时更新

    合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度

    字段的区分度越高,索引的查找速度越快

    库名应该尽量与应用名称保持一致,表的命名最好是业务名称_表名的方式

    无论是库名还是表名都禁用保留字,如desc、match、range等

    表名、字段名必须使用小写字母或数字

    自定义异常要做到“认知对等”,即:抛出者和接收者要保持对自定义异常的认知统一,接收方需要知道这种异常的含义和对应的处理方案

    IDE的text file encoding设置为UTF-8格式

    IDE中文件的换行符使用unix格式

    对于是与否概念的列名,必须使用is_abc 来表示

    数据类型是unsigned tiny int.( 1表示是,0表示否)

    返回的集合B没有实现Serializable接口,不能被序列化,所以不能应用于RPC场景

    在B集合中添加某个元素,那么A集合也会添加进去此元素

    对A元素个数的修改,会导致集合B的遍历产生ConcurrentModificationException 异常

    不要捕获异常后不处理,丢弃异常信息

    异常定义时区分unchecked / checked 异常,避免直接使用RuntimeException抛出

    构造方法中做的事情过多

    存在过多的全局变量和静态方法

    存在过多的外部依赖

    存在过多的条件语句

    推荐 if-else的方式可以改写成卫语句的形式

    尽量减少try-catch 块内的逻辑,定义对象、变量、获取数据库连接等操作可以移到try-catch块外处理

    在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有

    防止page size过大导致内存溢出

    防止正则输入源串拒绝服务ReDOS

    防止任意重定向

    预防 SQL 注入

    不要设定任何属性默认值

    禁止将URL、文件名、系统参数、数据库连接地址、业务规则的可变参数,硬编码在工程中

    long或者Long初始赋值时,必须是大写的L,不能小写

    当一个类有多个构造方法,或是多个同名方法,这些方法应该按顺序放置在一起,便于阅读

    相同参数类型,同等业务含义,才可以使用Java的可变参数,参数的类型尽量避免使用Object

    主键索引(primary key),字段类型为unsigned bigint、单表时推荐自增、步长为1

    唯一索引(unique key),命名规则为uk_字段名(如果多个字段继续下划线)

    普通索引(normal index),标记成idx_字段名(如果多个继续下划线)

    在接口类中的方法和属性使用public修饰符

    二方库里可以定义枚举类型

    bdb552dd4f02c60102e44c5146526988.png

    【包邮】2020新款夏被凉感丝夏凉被双人可水洗超软空调被单人夏季薄被子

    价格:64.35元

    券后价:36.35元

    商品链接:https://mobile.yangkeduo.com/app.html?use_reload=1&launch_url=duo_coupon_landing.html%3Fgoods_id%3D137608641464%26pid%3D10818730_145179483%26zs_duo_id%3D8197913%26cpsSign%3DCC_200714_10818730_145179483_1b0d47839ef813c4c07617494c89a0bf%26duoduo_type%3D2&campaign=ddjb&cid=launch_dl_force_

    展开全文
  • 主要留意本文的最后几个章节[ 回目录 ]3.3 线程池...而线程池维护着线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防...

    主要留意本文的最后几个章节

    [ 回目录 ]3.3 线程池创建编码规约

    1、不要在方法里创建线程池

    2、根据场景选择线程池

    97855deec2c7dfc0058bd5690b97e571.png


    建议不要用newFixedThreadPool

    1. 线程池定义

    线程池(英语:thread pool):一种线程使用模式。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。线程池可做隔离。

    [ 回目录 ]2. 常用线程池创建规范

    常用线程池一般有ThreadPoolExecutor、ScheduledThreadPoolExecutor、ForkJoinPool等

    [ 回目录 ]2.1 ThreadPoolExecutor

    java的线程池支持主要通过ThreadPoolExecutor来实现


    2.1.1 创建
    推荐:Spring
    <task:executor id="tableAndIndexCreateExecutor" pool-size="0-2" keep-alive="100" queue-capacity="50" rejection-policy="ABORT"/>
    或者
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)参数说明:corePoolSize:核心线程数,当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。workQueue: 线程阻塞队列,用于保存等待执行的任务的阻塞队列。
    可以选择以下几个阻塞队列:
    1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,按FIFO原则进行排序
    2)LinkedBlockingQueue:一个基于链表结构的阻塞队列,吞吐量高于ArrayBlockingQueue。newFixedThreadPool()使用了这个队列
    3)SynchronousQueue: 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量高于LinkedBlockingQueue,newCachedThreadPool()使用了这个队列
    4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。maximumPoolSize:线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。threadFactory(线程工厂):可以通过线程工厂为每个创建出来的线程设置更有意义的名字,如开源框架guavaRejectedExecutionHandler:饱和策略。一种策略还处理新提交的任务的策略。它可以有如下四个选项:
    1)AbortPolicy:直接抛出异常,默认情况下采用这种策略
    2)CallerRunsPolicy:用调用者所在线程来运行任务
    3)DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
    4)DiscardPolicy:不处理,丢弃掉
    更多的时候,我们应该通过实现RejectedExecutionHandler 接口来自定义策略,比如记录日志或持久化存储等。keepAliveTime:线程池的工作线程空闲后,保持存活的时间。所以如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程利用率。TimeUnit:线程活动时间,可选的单位有天(Days)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)
    2.1.2线程池任务提交
    可以使用execute和submit两个方法向线程池提交任务
    1)execute方法用于提交不需要返回值的任务
    2)submit方法用于提交一个任务并带有返回值,这个方法将返回一个Future类型对象。可以通过这个返回对象判断任务是否执行成功,并且可以通过future.get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成。

    [ 回目录 ]2.2 ScheduledThreadPoolExecutor

    支持周期性任务的调度的线程池


    2.2.1 线程池创建
    ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory,RejectedExecutionHandler handler)
    2.2.2 线程池任务提交
    1)使用继承功能submit和executor
    2)scheduleAtFixedRate 按指定频率周期执行某个任务,与任务执行时间无关
    3)scheduleWithFixedDelay 按指定频率间隔执行某个任务,与任务执行时间有关

    [ 回目录 ]2.3 ForkJoinPool

    计算密集型线程池

    2.3.1 线程池创建

    //ForkJoinPool的线程数上限取决于处理器的数量,线程工厂类型为DefaultForkJoinWorkerThreadFactory
    public ForkJoinPool() {
    this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
    defaultForkJoinWorkerThreadFactory, null, false);
    }
    //设置线程数上限
    public ForkJoinPool(int parallelism) {
    this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
    }
    //handler为线程出现异常后的处理器,asyncMode决定了QUEUE的类型
    public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory, UncaughtExceptionHandler handler, boolean asyncMode) {
    this(checkParallelism(parallelism),
    checkFactory(factory),
    handler,
    asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
    "ForkJoinPool-" + nextPoolId() + "-worker-");
    checkPermission();
    }

    2.3.2 任务提交

    a href="javascript:void(0);">-java代码01public class PiEstimateTask extends RecursiveTask<Double> {02 03 /**04 * π = 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - ……),05 * @return06 */07 @Override08 protected Double compute() {09 Double ret = Double.valueOf(0);10 if (true) {11 //计算12 } else {13 PiEstimateTask leftTask = new PiEstimateTask();14 PiEstimateTask rightTask = new PiEstimateTask();15 leftTask.fork();16 rightTask.fork();17 ret = leftTask.join() + rightTask.join();18 }19 return ret;20 }21 22 public static void main(String[] args) {23 ForkJoinPool pool = new ForkJoinPool(6);24 PiEstimateTask task = new PiEstimateTask();25 double result = pool.invoke(task);26 System.out.println("result:" + result);27 pool.shutdown();28 }29}

    [ 回目录 ]3. 线程池相关

    [ 回目录 ]3.1 线程池处理流程图

    bb1c97bf4c2747c0792e4e91efbb4f4e.png

    [ 回目录 ]3.2 其他创建线程池的方法

    在 JDK 1.5 之后推出了相关的 api,常见的创建线程池方式有以下几种:

    Executors.newCachedThreadPool():无限线程池,创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程

    Executors.newFixedThreadPool(nThreads):创建固定大小的线程池,超出的线程会在队列中等待。

    Executors.newSingleThreadExecutor():创建单个线程的线程池。

    Executors.newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

    [ 回目录 ]3.3 线程池创建编码规约

    1、不要在方法里创建线程池

    2、根据场景选择线程池

    97855deec2c7dfc0058bd5690b97e571.png

    [ 回目录 ]3.4 线程池相关接口和类

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

    ExecutorService 真正的线程池接口。

    ScheduledExecutorService 能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。

    ThreadPoolExecutor ExecutorService的默认实现。

    ScheduledThreadPoolExecutor 继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。

    展开全文
  • getmestage推荐使用ScheduledExecutorService方式处理Timer运行个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行ScheduledExecutorService并发运行个定时任务时,其中某线程抛出异常,...
  • Java编码指南(8)

    2011-07-28 11:19:23
    5.9 线程规范JAVA-33】 使用notifyAll(),而不是notify()【注意】说明·原因在同一个Object中有时会有线程同时在待机。使用notify()的话,将选择等待状态的线程中的1个,并将解除其Lock状态。此时,不能预测...
  • 关于多线程并行处理定时任务的情况,下列哪些说法符合 《阿里巴巴Java开发手册》: BCD A .推荐使用Timer方式处理。 B .推荐使用ScheduledExecutorService方式处理。 C .Timer运行多个TimeTask时,只要其中之一没有...
  • Java常用编码套路

    2020-09-23 17:02:25
    最近线上环境经常出现OOM,导致系统崩溃,在排查过程中,发现代码在使用多线程时有很多不规范的地方,导致内存泄露,因此我决定整理出一些常用的示例,在使用时 直接套用即可。因个人技术水平有限,如有错误,望指正...
  • 问题来源于编码规范的一个例子 一. 关于server模式下的主存和工作内存 规则40 多线程访问同一个可变变量,需增加同步机制 说明:根据Java Language Specification中对Java内存模型的定义, JVM中存在一个主内存...
  • 对于列排序,需要所有所有列排序方向一致,才能利用索引。 多选 19.关于类命名,下列哪些说法符合《阿里巴巴Java开发手册》:ABCD A .抽象类命名使用Abstract或Base开头。 B .异常类命名使用Exception结尾。 ...
  • 面试资料.pdf》据说是阿里 P8 级高级架构师吐血总结的一份 Java 核心知识.pdf, 内容覆盖很广,Java 核心基础、Java 多线程、高并发、Spring、微服务、Netty 与 RPC、Zookeeper、Kafka、RabbitMQ、Habase、设计模式、...
  • JAVA_API1.6文档(中文)

    万次下载 热门讨论 2010-04-12 13:31:34
    java.nio.charset 定义用来在字节和 Unicode 字符之间转换的 charset、解码器和编码器。 java.nio.charset.spi java.nio.charset 包的服务提供者类。 java.rmi 提供 RMI 包。 java.rmi.activation 为 RMI 对象...
  • java基础知识大全

    2015-03-26 00:22:33
    Java快速上手  JVM内存结构及其调优  在Eclipse下开发Java程序  在Linux下开发Java ... Java编码规范与样式    Java输入/输出流  Java多线程编程  Java常用实体类  Java常用集合类  Java正则表达式  XML
  • Java-并发-线程池

    2019-02-13 11:17:06
    在《阿里巴巴Java编码规范v1.4.0》之中,就可以看到以下描述: 【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 说明:使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统...
  • 首先,良好的编码规范非常重要。在 java 程序中,访问速度、资源紧张等问题的大部分原因,都是代码不规范造成的。单例的使用场景单例模式对于减少资源占用、提高访问速度等方面有很好处,但并不是所有场景都适用于...
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
  • 首先,良好的编码规范非常重要。在 java 程序中,访问速度、资源紧张等问题的大部分原因,都是代码不规范造成的。单例的使用场景单例模式对于减少资源占用、提高访问速度等方面有很好处,但并不是所有场景都适用于...
  • Java语法基础:类、抽象类、接L:l、内部类、匿名类、异常、编码规范。•Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。•Java图形编程:AWT(J 资源太大,传百度网盘了,链接在附件中,...
  • Java 代码常见优化方案

    千次阅读 2019-04-07 21:28:10
    首先,良好的编码规范非常重要。在 java 程序中,访问速度、资源紧张等问题的大部分原因,都是代码不规范造成的。 单例的使用场景 单例模式对于减少资源占用、提高访问速度等方面有很好处,但并不是所有场景都...
  • Java代码常见优化方案

    2020-02-22 15:24:22
    首先,良好的编码规范非常重要。在 java 程序中,访问速度、资源紧张等问题的大部分原因,都是代码不规范造成的。 单例的使用场景 单例模式对于减少资源占用、提高访问速度等方面有很好处,但并不是所有场景都适用...
  • java学习要点

    2013-04-04 13:21:26
    1、集合类:研究源码,找出各种集合类的在不同应用场景的区别,目标是可以实现...4、多线程:重点了解各种同步方式,Concurrent Programming in Java 5、了解虚拟机及GC,阅读JAVA虚拟机规范 6、重点编码规范和程...
  • Java学习路线

    2016-03-27 20:59:51
    算法 算法4th 集合框架 JDK+泛型 面向对象 敏捷软件开发,原则,模式,实践 ...多线程 Java并发编程实战 反射 JVM 设计模式 敏捷实践(JUnit、重构、TDD、持续集成) 编码规范 Effective Java Java E
  • JAVA核心技术

    千次阅读 2013-11-24 17:13:53
     ·Java语法基础:类、抽象类、接口、内部类、匿名类、异常、编码规范。  ·Java核心编程:流、多线程、实体类、集合类、正则表达式、XML、属性文件。  ·Java网络编程:Applet、Sockt/TCP/UDP、NIO、RMI
  • Java学习笔记

    2018-05-01 02:06:00
    自己学习Java的记录以及在其中踩得的一些坑... 0.0 基本问题 关于基本概念的理解 ...多线程线程池,对象锁、类锁 0.1 编码规范 对于编程课程的作业,很多程序是写完就扔,一千行一下的代码貌似即...

空空如也

空空如也

1 2 3 4 5 6
收藏数 119
精华内容 47
热门标签
关键字:

java编码规范多线程

java 订阅