最近浏览了一下阿里巴巴的Java开发手册,感觉内容确实非常的赞,发现了不少自己在编程中的误区,因此决定通过成文牢固掌握,文中将选取个人认为比较重要的部分进行描述与分析。”愿站在巨人的肩膀上,码出高效,码出质量“

概述

手册中内容很多,包括编码规约、工程结构、MySQL数据库、异常日志、安全规约、单元测试等6大部分。其中工程结构部分在整体上对项目进行了把控,编码规约和MySQL设计规约中有非常多的“最佳实践”,个人认为是最为有价值的部分。次重点安全规约很符合互联网场景的需要,异常日志和单元测试部分相对来说内容和价值相对小一点。
下图是个人对手册的简单汇总(将图片拖到浏览器新开页面,之后放大可以清晰很多),其中红星表示重点,黄色表示次重点。此外,其中的集合处理、并发处理、MySQL规约和工程结构有一定理解难度,会专门放到重难点增强一节进行详细分析。当然这只是个人的浅见,完整部分请见最下方的参考资料,目前阿里公司已推出这套规约的IDE插件,大家可以试试。

重难点增强

工程结构


Open Interface:提供RPC或Restful风格的接口,并通过框架进行网关安全控制、流量控制等。
 终端显示层:前端模板渲染并执行显示的层。
Web Layer: 主要是对访问控制进行转发, 各类基本参数校验, 或者不复用的业务简单处理等。
Service Layer:业务逻辑服务层。
Manager Layer:这一层比较有意思,既包含了常见的外部接口的Agent功能,也包含了对DAO接口的简单封装用于复用,还可以在改成构建对于DAO的缓存。
DAO Layer:与底层 MySQL、Hbase等进行数据交互,通常基于各类DAL框架。
ExternalInterface: 包括其它部门 RPC 开放接口, 基础平台, 其它公司的 HTTP 接口。
Tip: 实际项目中完全可以遵循该模式构建包的层次

集合处理

集合操作一直是一个关键点,常见的小技巧包括通过Set元素唯一的特性,可以快速对一个集合进行去重操作,JD8中通过steam流对集合操作做了不错的增强。合理利用好集合的有序性 (sort) 和稳定性 (order) ,避免集合的无序性 (unsort) 和
不稳定性 (unorder) 带来的负面影响,ArrayList是order&unsort;HashMap是unorder&unsort;TreeSet 是order&sort。
TIp: 不同类型Map集合K/V能不能存储null值的情况如下表所示

并发处理

合理的通过并发控制来高效利用系统资源是工程师永远的追求,该手册的不少要求很好的认识到自己在该方面的不足。
线程池的创建
过去一半都通过Executors 去创建线程池,实际上这是不合理的,比如FixedThreadPool的阻塞队列大小Integer.MAX_VALUE,很容易造成大量请求的堆积,造成OOM。而ScheduledThreadPool允许线程的数量为Integer.MAX_VALUE,更加容易出现OOM。因此必须使用ThreadPoolExecutor创建线程池,明确的制定线程池的参数,详情请见深入理解Java线程池一文
使用锁的原则
1.高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁 ; 能锁区块,就不要锁整个方法体 ; 能用对象锁,就不要用类锁。
2.对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
3.并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于 3 次
CountDownLatch
使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行至 await 方法,直到超时才返回结果。需要注意子线程抛出异常堆栈,不能在主线程的try-catch块中捕获到。
ThreadLocalRandom
避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降,推荐使用ThreadLocalRandom。
Volatile
volatile 解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。在完成饱汉的单例模式时,可以使用Volatile关键字实现延迟初始化。
LongAdder
对于count++操作,可以使用AtomicInteger count = new AtomicInteger();,JDK8中推荐使用LongAdder,通过减少乐观锁的重试次数提高性能。
HashMap
HashMap 在容量不够进行 resize 时由于高并发可能出现死链,导致 CPU 飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险。
ThreadLocal
ThreadLocal 对象建议使用 static修饰。这个变量是针对一个线程内所有操作共享的。

MYSQL规约

数据库方面的优化一直困扰着我,书上的一下几个原则给予个人在数据库优化方面不少启示。
索引长度
过去一直没有注意过索引还有长度这个概念,现在才知道在varchar等类型字段上建立索引时,可以指定索引长度,达到一定区分度即可,一般对于字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用count(distinct left( 列名, 索引长度 )) / count( * )的区分度来确定。

此外页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。索引文件具有B-Tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
order by
在有order by的场景,请注意利用索引的有序性。例如where a =? and b =? order by c的索引为a _ b _ c
覆盖索引
利用覆盖索引可以减少原表查询,通过索引页(目录)即可查到所需信息。通常来说,能够建立索引的种类包括主键索引、唯一索引、普通索引,而覆盖索引是查询的一种效果,可以通过explain查看到extra 列会出现using index
分页查询
MySQL并不是跳过offset行,而是取 offset + N 行,之后放弃offset行,返回所需N行,当数据量大时,推荐如下方式进行优化。先快速定位需要获取的 id 段,然后再关联:
SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id
SQL 性能优化的目标
至少要达到 range 级别, 要求是 ref 级别, 如果可以是 consts最好。
consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
ref 指的是使用普通的索引 (normal index) 。
range 对索引进行范围检索。
tip: type = index,索引物理文件全扫描,速度非常慢,这个 index 级别比较 range 还低,与全表扫描是小巫见大巫。
组合索引
区分度最高的在最左边,对于where a =? and b =?来说,a 列的值越唯一越好。此外,存在非等号和等号混合判断条件时, 在建索引时, 请把等号条件的列前置。
隐式转换
防止因字段类型不同造成的隐式转换,导致索引失效,当数据查询超时,也需要把此作为很重要的考虑部分。

参考资料
阿里巴巴Java开发手册
阿里规约github

《阿里巴巴Java工作手册》学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

  10. ucos实时操作系统学习笔记——任务间通信(消息)

    ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox.为什么有了qu ...

随机推荐

  1. php中数组相关

    <?php//参数默认值function abc($a,$b,$c = 0){ echo $a,$b,$c;}abc(1,3);结果为:130:echo "<br>&quo ...

  2. 微信企业号C#开发配置API

    微信开发第一步 :   配置API,实现接收消息服务配置 1.在下图界面先填好内容,事件消息处理可自行选择,我这里是没处理的 2.第二步: 使用vs 进行代码的编写,以下是我的代码.LogTextHe ...

  3. Linux 进程与信号的概念和操作

    进程 主要参考: http://www.bogotobogo.com/Linux/linux_process_and_signals.php 信号与进程几乎控制了操作系统的每个任务. 在shell中输 ...

  4. UWP 绘制图形

    UWP图形和wpf变化不多 一般用到有椭圆.长方形.多边形.线 不过如果用的好,可以做出很漂亮的界面 一般使用画图都是使用Shape 类,Shape 类具有一个与其关联的画笔并可以呈现到屏幕,包括 L ...

  5. 系统装机硬盘格式 >> GPT或者UEFI

    预装Win8系统的电脑,硬盘都是采用这种分区格式,因为出厂安装时,是以Uefi方式启动安装的. 简单的办法,仍安装Win8系统:或者是转换磁盘分区格式为MBR,不用任何软件就可实现,需要重建分区表,会 ...

  6. 解析 .Net Core 注入 (1) 注册服务

    在学习 Asp.Net Core 的过程中,注入可以说是无处不在,对于 .Net Core 来说,它是独立的一个程序集,没有复杂的依赖项和配置文件,所以对于学习 Asp.Net Core 源码的朋友来 ...

  7. PHP异常处理机制

    1. 异常: 异常(Exception)用于在指定的错误发生时改变脚本的正常流程. 当异常被触发时,通常会发生: (1)当前代码状态被保存: (2)代码执行被切换到预定义的异常处理器函数: (3)根据 ...

  8. Ajax中与服务器的通信【发送请求与处理响应】

    一.发送请求 Ajax中通过XMLHttpRequest对象发送异步方式的后台请求时.通常有两种方式的请求,一种是GET请求,另一种是POST请求.发送请求一般要经过4个步骤分别是: (1)初始化XM ...

  9. 【问题排查】fastjson线上排坑记

    前言 版本上线时发现fastjson的toString方法的返回的字符串与与之前版本的toString方法返回的字符串不相同,这导致依赖toString进行md5计算所得到的结果不相同,更进一步导致其 ...

  10. 博客迁移至 http://www.loveli.site

    对于博客园的Markdow 支持太过...,你懂的,  以后博客迁移至:http://www.loveli.site