码出高效读书笔记(上)

2020/03/05

第1 章 计算机基础

大道至简,盘古生其中。计算机的基础世界一切都是0和1组成的。

组成原理

0与1

无论是图形图像的渲染、网络远程共享 还是大数据计算,归根结底都是 0与1的信号处理。

信息存储和逻辑计算的元数据 ,只能是0和1. 但是它们在不同介质里的物理表现方式却是不

一样的 ,如:极管的断电与通电、 CPU 的低电平与高电平、碰盘的电荷左右方向。

二级制和十进制 二进制逢二进一

32路的电路 能够表示的最大数 2^32-1=4294967295

平时所说的32位机器就是能够同时处理字长位32位的电路信号

为什么要用补码?

加法器是高频运算,使用用同一个运算器,可以减少变量存储的开销。

降低了cpu内部的复杂度,对于寄存器和运算器 都会减少很大的负担。

一条电路成为1位,记1bit

位移运算

向右移1位,近似表示除于2(奇数并不是完全除2)

在左移<<与 移>>两种

算中 符号位均参与移动 除负数往右移动 高位补 1之外,其他情况均在空位处补0

无符号位移运算

对于三个大于号的>>> 无符号向右移动 注意不存在<<<无符号向左移动的运

算方式) 当向右移动时 正负数高位均补 0,正数不断向右移动的最小值是0

负数不断向 移动的最小值是1 。(场景高位转地位的场景)

怎么高效地交换两个值?

image-20200618155608119

取出特定为用& &0 无论是什么都是 0 &1 还是本身

当一个整数%2的n次方 完全等价与&这个数的2的n-1次方 %2 &1

*2 «1 *4«2 *8«3

/2 »1 /4»2 /8»3

位移运算可以快速地实现乘除运算,那位移时要注意什么?

浮点数

浮点数 ,符号位 +幂指位+数值位

​ 32(1+8+23)64(1+11+52)

float a = lf; 
float b = 0 . 9f ; 
//结果为0.100000024
float f = a - b;
和实际结果存在误差

浮点数的存储与计算为什么总会产生微小的误差?

  • 存在精度问题的原因其实就在于浮点数十进制转二进制的过程中,由于位数限制(有效数字只有23位),所以会存在丢失位数的情况,在计算过程中的对阶和规格化过程中,也存在着某些位数丢失的情况。

  • 在要求绝对精确表示的业务场景下,比如金融行业的货币表示,推荐使用整型存储其最小单元的值,展示时可以转换成该货币的常用单位,比如人民币使用分存储,美元使用美分存储;
  • 在要求精确表示小数点n位的业务场景下,比如圆周率要求存储小数点后1000位数字,使用单精度和双精度浮点数类型保存是难以做到的,这时推荐采用数组保存小数部分的数据;
  • 在比较浮点数时,由于存在误差,往往会出现意料之外的结果,所以禁止通过判断两个浮点数是否相等来控制某些业务流程; 在数据库中保存小数时,推荐使用demical类型,禁止使用float类型和double类型,因为这两种类型在存储的时候存在精度损失的问题。

字符集与乱码

为了减少麻烦,所有情况下的字符集设置最好是一致的。

CPU 与内存

cpu内部十分复杂,总的来说是由控制器 和 运算器组成的。内部寄存器使这两者跟加高效

image-20200618163747009

Java操作内存交给JVM,付出的代价是慢

TCP/IP

发送和接收数据的过程需要相应的协议来支撑,按互相可以理解的方式进行数据的打包与解包

image-20200618164857949

image-20200618165000852

​ 链路层报文结构

mac地址全球唯一 使用16进制表示

总结:

程序在发送消息时,应用层接既定的协议打包数据 随后由传输层加

上双方的端口 ,由网络层加上双方的 IP 地址,由链路层加上双方的 MAC 地址

将数据拆分成数据帧 经过多个路由器 网关后到 达目标机器。简而言之 就是按

端口→ IP 地址→ MAC 地址 这样的路径进行数据的封装和发送 解包的时候反过

来操作即可

IP协议

IP是面向无连接,无状态的,没有额外的机制保持包是否送达

为什么有mac地址 还要IP协议?

分层管理

image-20200618170100475

数据包生存时间 TTL 他是数据包可经过最多的路由器总数。 没经过减1 为0时抛弃。 并发送ICMP保温到源主机。

ICMP检测网络是否通畅

TCP

是 一种面向连接、确保数据在端到端间可靠传输的协议

image-20200618170650515

由于TCP包头中存在扩展字段,所以通过长度为4个bit的头部长度表示tcp的报文的大小,这样才能计算数据部分的开始位置

SYN:( Synchronize Sequence Numbers )用作建立连接时的同步信号

ACK: ( Acknowledgement )用于对收到的数据进行确认,所确认的数据由确认序列号表示;

FIN:( Finish )表示后面没有数据需要发送,通常意昧着所建立的连接需要关闭了。

TCP 建立连接:

三次握手

image-20200618172019147

为什么要三次握手?

主要为了两个主要目的:信息对等和防止超时

image-20200618190601573

三次握手 也是防止超时导致脏链接

从编程的角度,TCP的连接 是通过文件描述符(fd)完成, 当fd不足时会出现 “open too many

files 错误而使得无法建立更多的连接。

TCP四次挥手

tcp是全双工通信,双方都能作为数据的发送方 和 接收方。

image-20200619004548318

四次挥手断开连接用通俗的说法可以形象化地这样描述。

男生我们分手吧。

女生好的,我的东西收拾完,发信息给你。( 此时男生不能再拥抱女生了。)

( 个小时后)

女生,我收拾好了,分手吧。 (此时 女生也不能再拥抱男生了。)

男生。好的。 (此时 双方约定经过 个月的过渡期,双方才可以分别找新的

对象。)

TIME_WAIT:RFC793规定为2分钟,极大造成资源的浪费 为何不直接进入closed状态

1.确保被动关闭方顺利进入closed状态

防止失效请求。这样做是为了防止己失效连接的请求数据包与正常连接的

请求数据包混淆而发生异常。

所以,建议将高并发服务器 TIME WAIT 超时时间调小。

连接池

连接的频繁创建与断开,是非常消耗资源的

连接池最小连接数: 一直保持的连接数

连接池最大连接数: 连接池能申请的最大连接数,如果超过则被放到等待队列中

-般可以把连接池的最大连接数设置在 30个左右

在数据库层面的请求应答时间必须在 I00ms 以内,秒级的 SQL

查询通常存在巨大的性能提升空间,有如下应对方案,

  • 建立高效且合适的索引 explain 还要考虑索引不生效的情况
  • 排查连接资源 未显式关闭的·情况 特别注意ThreadLocal 或 流式计算中 使用数据库链接的地方
  • 合并短的请求。
  • 合理拆分多个表 join SQL 是超过三个表则禁止 join 多表查询的时候 要确定被关联字段添加索引
  • 使用临时表
  • 应用层改造 数据结构优化 并发线程改造
  • 改用其它数据库

信息安全

DDos csrf xss

CIA原则

保密性 加密

完整性 通常使用MD5和数字签名

可用性 访问控制 限流

SQL注入

SQL 注入式攻击是未将代码与数据进行严格的隔离 ,导致在读取用户数据的时候 错误地把数据作为代码的一部分执行

防止:

( I )过滤异户输入参&中的阿弥字符 ,从而降低被 SQL ,t 入的风险。

( )禁止通过字符南拼撞的 SQL 吾旬 ,严恪使用参数绑定传人的 SQL 参数

( 3 )合理使月数据库击可框豆、提供的防左入机制。

CSRF

在用户并不知惰的情况下 冒充用户发起请求 在当前已经登录的 Web

用程序上执行恶意操作,如恶意发帖、修改密码、发邮件等。

防范 CSRF 漏洞主要通过以下方式

( I ) CSRF Token 验证,利用浏览器的同源限制,在 HTTP 接口执行前验证页面

或者 Cookie 中设置的 Token ,只有验证通过才继续执行请求。

( 人机交互 ,比如在调用上述网上银行转账接口时校验短信验证码。

XSS

跨站脚本攻击,通过向正常用户请求的 HTML 页面中插入恶意脚本,

从而可以执行任意脚本。

xss 主要分为反射型 xss 、存储型 xss DOM xss

xss 主要用于信息窃取、破坏等目的。

HTTPS

传输层本身是没有加密的

SSL 协议工作于传输层与应用层之间,为应用提供数

据的加密传输。

而 HTTPS 的全称是 HTTP over SSL ,简单的理解就是在之前的 HTTP

传输上增加了 SSL 协议的加密能力。

加密

我们可以通过对称加密算法对数据进行加密,比如 DES

密钥几乎没有什么保密性可言,如果与每一个用户之间

都约定一个独立的密钥,如何把密钥传输给对方,又是 个安全难题。

RSA 出现了。它把密码革命性地分成公钥和私钥,由于两个密钥并不相同,所以称

为非对称加密。私钥是用来对公钥加密的信息、进行解密的,是需要严格保密的。公钥

是对信息进行加密,任何人都可以知道,包括黑客。

非对称加密的安全性是基于大质数分解的困难性

RSA存在的问题· 信任危机 (即公钥不是真正的发送方 发送的)

CA ( Certificate Authority )就是颁发 HTTPS 证书的组织。

访问一个 HTTPS 的网站的大致流程如下,

( I )浏览器向服务器发送请求,请求中包括浏览器支持的协议,并附带一个随

机数。

( )服务器收到请求后,选择某种非对称加密算法,把数字证书签有公钥、身

份信息发送给浏览器,同时也附带一个随机数。

( )浏览器收到后、验证证书的真实性,用服务器的公铝发送握手信息给服务器。

( 服务器解密后 使用主前的随机数计算出,个对称加密的密钥 以此作为

加密信息并发送。

( 后续所有的信息发送都是以对称加密方式进行的。

TSL式SSL的3.0版本

第2 章 面向对象

OOP理念

OOP (面向对象编程)是面向过程的进一步发展,它推动了高级语言的发展。OOP的抽象、封装、继承、多态,使软件大规模化成为可能。

OOP实践了软件的三个主要目标:可维护,可扩展和可重用性

抽象

正确而严谨的业务抽象和建模分析能力是后续的封装、继承、多态的基础

在面向对象的思维中,抽象分为归纳和演绎。

前者是从具体到本质,从个性到共性,将一类对象的共同特征进行

归一化的逻辑思维过程 后者则是从本质到具体,从共性到个性,逐步形象化的过程。

封装

是在抽象基础上决定信息是否公开,以及公开等级,核心问题是以什么样的方式暴露哪些信息。

抽象只为了找到属性和行为的共性,属性是行为的基础,具有一定的敏感性,不能直接对外暴露

设计模式的七大原则之一的 迪米特法则就是对 封装的具体要求

继承

封装使软件在多变的情况下,基础模块可以直接被复用,或者增强复用。

继承是is-a关系,怎么满足?

里氏置换原则:任何父类能出现的地方,子类都能够出现

继承要注意 方法污染 和 方法爆炸

所以:优先采用组合或聚合的类关系来复用其他类的能力,而不是继承。

多态

同一个方法产生不同的运行结果,使同一个行为具有不同的表现形式。

是以覆写为基础实现面向对象的特性。

抽象类 和接口

抽象类和接口都是对实体类进行更高层次的抽象,仅定义公共行为和特性。

共同点: 都不能被实例化

image-20200619155220420

抽象类在被继承时体现的是 is 关系,接口在被实 时体现的是 can do 关系。

抽象类通常是对同类事物相对具体的抽象,通常包含抽象方法、实体方法、属性变量。

can do 关系要符合接口 隔离 实现类要有能力去实现并执行接口 中定义的行为,

抽象类是 模板类设计,接口是契约式设计

优先定义为接口

内部类

内部类本身是类的属性

可以为 class enum ,甚至是 interface ,

·静态内部类,如 static class StaticinnerC!ass {} ;

·成员内部类,如: private class InstancelnnerC!ass {} ;

·局部内部类,定义在方法或者表达式内部,

·匿名内部类,如: (new Thread(){} ).start()。

访问权限

image-20200619171223144

this和super

image-20200619171702709

类关系

  • [ 继承 ] extends (is-a)

  • [ 实现 ] implements (can do)

  • [ 组合 ] 类是成员变量 contain-a)

  • { 聚合 ] 类是成员变量(has a)

  • [ 依赖 ] import (use-a)

image-20200619172457594

序列化

将对象转化为二进制流 称为对象的序列化

将二进制流恢复为对象的过程,称为反序列化

1.Java原生序列化

不支持跨语言

2.Hessian 序列化

协议简单 ,高效

跨语言

缩短二进制流

3.JSON序列化 抛弃了类型信息

json可读性好,方便调试

transient 序列化要有安全的防范意识

攻击者可以利用反序列化构造恶意代码

方法

入参保护

常见于批量接口 不然会导致服务内存被塞满,无任何处理能力

参数校验

构造方法

构造方法不要包含业务逻辑

初始化业务逻辑 放到某个方法内,当完成初始化 ,再显示调用

image-20200619175009923

静态方法

当类加载时,即分配相应的内存空间

通常静态方法用于定义工具类的方法等,静态方法如果使用了可修改的对象,那

么在并发时会存在线程安全问题。所以,工具类的静态方法与单例通常是相伴而生的。

非静态代码块又称为局部代码块,是极不推荐的处理方式

可以使用静态代码块实现类加载判断、属性初始化、环境配置等。

覆盖

方法的覆写可以总结成容易记忆的口诀 大两小两同

  • 一大 子类的方法访问权限控制符只能相同或变大。

  • 两小 抛出异常和返回值只能变小 能够转型成父类对象。子类的返回值、

抛出异常类型必须与父类的返回值、抛出异常类型存在继承关系。

  • 两同 方法名和参数必须完全相同。

泛型

类型参数话,解决不确定具体对象类型的问题。

没有泛型往往存在类型安全问题

泛型可以定义再类、接口和方法中

E括代表 Element ,用于集合中的元素;

T代表 the Type of object ,表示某个类; K代表key、V 代表 Value ,用于键值对元素。

(1)尖捂号里的每个元素都指代一种未知类型。 而仅仅是一个代号

(2)尖括号的位置非常讲究,必须在类名之后 方法返回值之前。

(3)泛型定义只具备Object的能力

泛型的好处:

1.代码安全

2.提高可读性

3.代码重用

基本数据类型

image-20200619185200179

对象头占12个字节

image-20200619191146081

包装类型

应为Java设计的初衷是一切皆对象, 很多时候需要对象来做

包装类的存在解决了基本数据类型无法做到的事情泛型类型参数、序列化、类型转换、高频区间数据缓存。

什么时候使用包装类还是基本数据类型?

1.所有的POJO类属性,必须使用包装类

2.RPC方法返回值和参数必须使用包装类

3.所有局部变量推荐使用基础数据类型

字符串

Strin 对象赋值操作后 会在常量池中进行缓存,如果下次申请创建对象时 缓存中已经存在,则直接返回相应引用给创建者。

StringBuilder 线程不安全

第3 章 代码风格

存储一对多的关系

JSON方式,XML方式,逗号隔开,多字段存储

推荐使用JSON方式

删除字段名称

is_deleted 使用1/0表示已删除和未删除状态

第4 章 走进JVM

字节码

字节码必须通过类加载过程加载到 JVM 环境后,才可以执行

执行有三种模式

第一,解释执行

第二, JIT 编译执行

第三, JIT 编译与解释混合执行(主流 JVM默认执行模式)

混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间。

随着时间推进 JVM 通过热点代码统计分析 识别热点数据,将热点数据转化为机器码,直接交由CPU执行。

类加载过程

image-20200619210652805

newInstance( )是一个方法,而new是一个关键字,其次,Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用new关键字生成对象没有这个限制。

类加载器 怎么定位具体文件并读取?

image-20200620104512039

为什么使用类加载器?

(1) 隔离加载类 在某些框架内进行中间件 与 应用的模块隔离,把类加载到不同的环境

(2)修改类的加载方法 类的加载模型非强制,并非一定要引入。

(3)扩展加载源

(4)防止源码泄露

继承classLoader 重写 findClass 调用defineClass

内存布局

image-20200620112427030

image-20200620163451400

元空间

JVM版本 sun Hostspot

JDK8 之前 是存在永久区的

1.它是固定大小,很难进行调优

2.如果动态加载的类过多,会永久代的OOM

3.永久代在垃圾回收方面也有很多问题

JDK8 使用元空间代替 永久代

在本地内存中分配

虚拟机栈

先进后出的数据结构,就像子弹的弹夹

栈是描述方法执行的内存区域,它是线程私有的

StackOverflowError 表示栈溢出 导致内存耗尽,通常出现在递归调用中

image-20200620164550071

局部变量表:是存放方法参数和局部变量的地方

操作栈:初始状态为空的桶式结构栈

动态链接:每个栈帧中包含一个在常量池中对当前方法的引用 目的是支持方法调用过程的动态连接。

方法返回地址 :

  • 返回值压入上层调用栈帧。

  • 异常信息抛给能够处理的栈帧。。

  • PC 数器指向方法调用后的下一条指令。

本地方法栈

调用操作系统方法

程序计数寄存器

CPU时间片限制,任何时候只有一个线程执行指令

程序计数寄存器用来存放执行指令的偏移量和行号指示器

线程执行和恢复都需要依赖程序计数器 线程之间互不影响

从线程共享的角度:

堆和元空间是所有线程共享的,而虚拟机栈、本地方法栈、程序计数器是线程内部私有的

image-20200620171506507

对象实例化

当new对象的时候

1.确认元信息是否存在

2.分配 对象内存

3.设置默认值

4.设置头信息

设置新对象的晗希码、 GC 信息、锁信息、对象所属的类元信息等。

这个过程的具体设置方式取决于 口币 实现。

5.执行init方法

初始化成员变量,执行实例化代码块,调用类的构造方法,

并把堆内对象的首地址赋值给引用变量。

垃圾回收

清楚不再使用的对象,自动释放内存空间

如何判断对象是否存活?

1.标记清理算法

会引起大量空间碎片

2.标记整理算法

把存活的整理在内存连续的一段,最后把之外的清理掉

Mark_Copy算法

Serial 回收器是一个主要应用于 YGC 的垃圾回收器,采用串行单线程的方法完成GC任务

STOP THE WORLD 即垃圾回收会暂停整个应用程序的执行

FGC时间较长,频繁会影响行用程序的性能

image-20200620175046888

CMS 回收器( Concurrent Mark Sweep Collector )是回收停顿时间比较短、目前

比较常用的垃圾回收器。

Hotspot JDK7 推出了新代 1 ( Garbage-First Garbage Collector 垃圾回收

Post Directory