auto commit
This commit is contained in:
+14
-14
@@ -57,17 +57,17 @@
|
||||
|
||||
URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基本都是 URL。
|
||||
|
||||
<br><div align="center"> <img src="../pics//4102b7d0-39b9-48d8-82ae-ac4addb7ebfb.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//4102b7d0-39b9-48d8-82ae-ac4addb7ebfb.jpg"/> </div>
|
||||
|
||||
## 请求和响应报文
|
||||
|
||||
**请求报文**
|
||||
|
||||
<br><div align="center"> <img src="../pics//22b39f77-ac47-4978-91ed-84aaf457644c.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//22b39f77-ac47-4978-91ed-84aaf457644c.jpg"/> </div>
|
||||
|
||||
**响应报文**
|
||||
|
||||
<br><div align="center"> <img src="../pics//00d8d345-cd4a-48af-919e-209d2788eca7.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//00d8d345-cd4a-48af-919e-209d2788eca7.jpg"/> </div>
|
||||
|
||||
# HTTP 方法
|
||||
|
||||
@@ -120,13 +120,13 @@ GET 的传参方式相比于 POST 安全性较差,因为 GET 传的参数在 U
|
||||
|
||||
TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪),因此更不会去使用它。
|
||||
|
||||
<br><div align="center"> <img src="../pics//c8637fd2-3aaa-46c4-b7d9-f24d3fa04781.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c8637fd2-3aaa-46c4-b7d9-f24d3fa04781.jpg"/> </div>
|
||||
|
||||
## CONNECT:要求用隧道协议连接代理
|
||||
|
||||
主要使用 SSL(Secure Sokets Layer,安全套接字)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
|
||||
|
||||
<br><div align="center"> <img src="../pics//5994928c-3d2d-45bd-abb1-adc4f5f4d775.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//5994928c-3d2d-45bd-abb1-adc4f5f4d775.jpg"/> </div>
|
||||
|
||||
# HTTP 状态码
|
||||
|
||||
@@ -168,7 +168,7 @@ TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing
|
||||
|
||||
- **401 Unauthorized** :该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。如果之前已进行过一次请求,则表示用户认证失败。
|
||||
|
||||
<br><div align="center"> <img src="../pics//b1b4cf7d-c54a-4ff1-9741-cd2eea331123.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//b1b4cf7d-c54a-4ff1-9741-cd2eea331123.jpg"/> </div>
|
||||
|
||||
- **403 Forbidden** :请求被拒绝,服务器端没有必要给出拒绝的详细理由。
|
||||
|
||||
@@ -261,7 +261,7 @@ HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使
|
||||
|
||||
服务器发送的响应报文包含 Set-Cookie 字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。下次再发送请求时,从浏览器中读出 Cookie 值,在请求报文中包含 Cookie 字段,这样服务器就知道客户端的状态信息了。Cookie 状态信息保存在客户端浏览器中,而不是服务器上。
|
||||
|
||||
<br><div align="center"> <img src="../pics//ff17c103-750a-4bb8-9afa-576327023af9.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//ff17c103-750a-4bb8-9afa-576327023af9.png"/> </div>
|
||||
|
||||
Set-Cookie 字段有以下属性:
|
||||
|
||||
@@ -298,13 +298,13 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
|
||||
|
||||
当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源,如果每进行一次 HTTP 通信就要断开一次 TCP 连接,连接建立和断开的开销会很大。 **持久连接** 只需要进行一次 TCP 连接就能进行多次 HTTP 通信。HTTP/1.1 开始,所有的连接默认都是持久连接。
|
||||
|
||||
<br><div align="center"> <img src="../pics//c73a0b78-5f46-4d2d-a009-dab2a999b5d8.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c73a0b78-5f46-4d2d-a009-dab2a999b5d8.jpg"/> </div>
|
||||
|
||||
持久连接需要使用 Connection 首部字段进行管理。HTTP/1.1 开始 HTTP 默认是持久化连接的,如果要断开 TCP 连接,需要由客户端或者服务器端提出断开,使用 Connection: close;而在 HTTP/1.1 之前默认是非持久化连接的,如果要维持持续连接,需要使用 Keep-Alive。
|
||||
|
||||
管线化方式可以同时发送多个请求和响应,而不需要发送一个请求然后等待响应之后再发下一个请求。
|
||||
|
||||
<br><div align="center"> <img src="../pics//6943e2af-5a70-4004-8bee-b33d60f39da3.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//6943e2af-5a70-4004-8bee-b33d60f39da3.jpg"/> </div>
|
||||
|
||||
## 编码
|
||||
|
||||
@@ -320,7 +320,7 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
|
||||
|
||||
例如,上传多个表单时可以使用如下方式:
|
||||
|
||||
<br><div align="center"> <img src="../pics//2279cc60-9714-4e0e-aac9-4c348e0c2165.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2279cc60-9714-4e0e-aac9-4c348e0c2165.png"/> </div>
|
||||
|
||||
## 范围请求
|
||||
|
||||
@@ -348,19 +348,19 @@ Expires 字段可以用于告知缓存服务器该资源什么时候会过期。
|
||||
|
||||
使用代理的主要目的是:缓存、网络访问控制以及访问日志记录。
|
||||
|
||||
<br><div align="center"> <img src="../pics//c07035c3-a9ba-4508-8e3c-d8ae4c6ee9ee.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c07035c3-a9ba-4508-8e3c-d8ae4c6ee9ee.jpg"/> </div>
|
||||
|
||||
**网关**
|
||||
|
||||
与代理服务器不同的是,网关服务器会将 HTTP 转化为其它协议进行通信,从而请求其它非 HTTP 服务器的服务。
|
||||
|
||||
<br><div align="center"> <img src="../pics//81375888-6be1-476f-9521-42eea3e3154f.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//81375888-6be1-476f-9521-42eea3e3154f.jpg"/> </div>
|
||||
|
||||
**隧道**
|
||||
|
||||
使用 SSL 等加密手段,为客户端和服务器之间建立一条安全的通信线路。
|
||||
|
||||
<br><div align="center"> <img src="../pics//64b95403-d976-421a-8b45-bac89c0b5185.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//64b95403-d976-421a-8b45-bac89c0b5185.jpg"/> </div>
|
||||
|
||||
# HTTPs
|
||||
|
||||
@@ -380,7 +380,7 @@ HTTPs 并不是新协议,而是 HTTP 先和 SSL(Secure Socket Layer)通信
|
||||
|
||||
HTTPs 采用 **混合的加密机制** ,使用公开密钥加密用于传输对称密钥,之后使用对称密钥加密进行通信。(下图中,共享密钥即对称密钥)
|
||||
|
||||
<br><div align="center"> <img src="../pics//110b1a9b-87cd-45c3-a21d-824623715b33.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//110b1a9b-87cd-45c3-a21d-824623715b33.jpg"/> </div>
|
||||
|
||||
## 认证
|
||||
|
||||
|
||||
+13
-13
@@ -65,7 +65,7 @@
|
||||
|
||||
# 内存模型
|
||||
|
||||
<br><div align="center"> <img src="../pics//dc695f48-4189-4fc7-b950-ed25f6c80f82.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//dc695f48-4189-4fc7-b950-ed25f6c80f82.jpg"/> </div>
|
||||
|
||||
注:白色区域为线程私有的,蓝色区域为线程共享的。
|
||||
|
||||
@@ -225,7 +225,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
### 2.1 标记 - 清除算法
|
||||
|
||||
<br><div align="center"> <img src="../pics//a4248c4b-6c1d-4fb8-a557-86da92d3a294.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//a4248c4b-6c1d-4fb8-a557-86da92d3a294.jpg"/> </div>
|
||||
|
||||
将需要回收的对象进行标记,然后清除。
|
||||
|
||||
@@ -238,7 +238,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
### 2.2 复制算法
|
||||
|
||||
<br><div align="center"> <img src="../pics//e6b733ad-606d-4028-b3e8-83c3a73a3797.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//e6b733ad-606d-4028-b3e8-83c3a73a3797.jpg"/> </div>
|
||||
|
||||
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
|
||||
|
||||
@@ -248,7 +248,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
### 2.3 标记 - 整理算法
|
||||
|
||||
<br><div align="center"> <img src="../pics//902b83ab-8054-4bd2-898f-9a4a0fe52830.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//902b83ab-8054-4bd2-898f-9a4a0fe52830.jpg"/> </div>
|
||||
|
||||
让所有存活的对象都向一段移动,然后直接清理掉端边界以外的内存。
|
||||
|
||||
@@ -263,13 +263,13 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
## 3. 垃圾收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//c625baa0-dde6-449e-93df-c3a67f2f430f.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c625baa0-dde6-449e-93df-c3a67f2f430f.jpg"/> </div>
|
||||
|
||||
以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。
|
||||
|
||||
### 3.1 Serial 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//22fda4ae-4dd5-489d-ab10-9ebfdad22ae0.jpg"/> </div>
|
||||
|
||||
它是单线程的收集器,不仅意味着只会使用一个线程进行垃圾收集工作,更重要的是它在进行垃圾收集时,必须暂停所有其他工作线程,往往造成过长的等待时间。
|
||||
|
||||
@@ -279,7 +279,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
### 3.2 ParNew 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//81538cd5-1bcf-4e31-86e5-e198df1e013b.jpg"/> </div>
|
||||
|
||||
它是 Serial 收集器的多线程版本。
|
||||
|
||||
@@ -301,7 +301,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。
|
||||
|
||||
### 3.4 Serial Old 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//08f32fd3-f736-4a67-81ca-295b2a7972f2.jpg"/> </div>
|
||||
|
||||
Serial Old 是 Serial 收集器的老年代版本,也是给 Client 模式下的虚拟机使用。如果用在 Server 模式下,它有两大用途:
|
||||
|
||||
@@ -310,7 +310,7 @@ Serial Old 是 Serial 收集器的老年代版本,也是给 Client 模式下
|
||||
|
||||
### 3.5 Parallel Old 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//278fe431-af88-4a95-a895-9c3b80117de3.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//278fe431-af88-4a95-a895-9c3b80117de3.jpg"/> </div>
|
||||
|
||||
是 Parallel Scavenge 收集器的老年代版本。
|
||||
|
||||
@@ -318,7 +318,7 @@ Serial Old 是 Serial 收集器的老年代版本,也是给 Client 模式下
|
||||
|
||||
### 3.6 CMS 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//62e77997-6957-4b68-8d12-bfd609bb2c68.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//62e77997-6957-4b68-8d12-bfd609bb2c68.jpg"/> </div>
|
||||
|
||||
CMS(Concurrent Mark Sweep),从 Mark Sweep 可以知道它是基于 标记 - 清除 算法实现的。
|
||||
|
||||
@@ -343,7 +343,7 @@ CMS(Concurrent Mark Sweep),从 Mark Sweep 可以知道它是基于 标记
|
||||
|
||||
### 3.7 G1 收集器
|
||||
|
||||
<br><div align="center"> <img src="../pics//f99ee771-c56f-47fb-9148-c0036695b5fe.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f99ee771-c56f-47fb-9148-c0036695b5fe.jpg"/> </div>
|
||||
|
||||
G1(Garbage-First)收集器是当今收集器技术发展最前沿的成果之一,它是一款面向服务端应用的垃圾收集器,HotSpot 开发团队赋予它的使命是(在比较长期的)未来可以替换掉 JDK 1.5 中发布的 CMS 收集器。
|
||||
|
||||
@@ -433,7 +433,7 @@ JVM 为对象定义年龄计数器,经过 Minor GC 依然存活且被 Survivor
|
||||
|
||||
## 1 类的生命周期
|
||||
|
||||
<br><div align="center"> <img src="../pics//32b8374a-e822-4720-af0b-c0f485095ea2.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//32b8374a-e822-4720-af0b-c0f485095ea2.jpg"/> </div>
|
||||
|
||||
包括以下 7 个阶段:
|
||||
|
||||
@@ -610,7 +610,7 @@ public static void main(String[] args) {
|
||||
|
||||
应用程序都是由三种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。下图展示的类加载器之间的层次关系,称为类加载器的双亲委派模型(Parents Delegation Model)。该模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器,这里类加载器之间的父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)的关系实现。
|
||||
|
||||
<br><div align="center"> <img src="../pics//2cdc3ce2-fa82-4c22-baaa-000c07d10473.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2cdc3ce2-fa82-4c22-baaa-000c07d10473.jpg"/> </div>
|
||||
|
||||
**工作过程**
|
||||
|
||||
|
||||
+9
-9
@@ -48,7 +48,7 @@ File 类可以用于表示文件和目录,但是它只用于表示文件的信
|
||||
|
||||
# 字节操作
|
||||
|
||||
<br><div align="center"> <img src="../pics//8143787f-12eb-46ea-9bc3-c66d22d35285.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//8143787f-12eb-46ea-9bc3-c66d22d35285.jpg"/> </div>
|
||||
|
||||
Java I/O 使用了装饰者模式来实现。以 InputStream 为例,InputStream 是抽象组件,FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作。FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能,例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。
|
||||
|
||||
@@ -140,7 +140,7 @@ is.close();
|
||||
|
||||
Socket 通信模型
|
||||
|
||||
<br><div align="center"> <img src="../pics//fa4101d7-19ce-4a69-a84f-20bbe64320e5.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//fa4101d7-19ce-4a69-a84f-20bbe64320e5.jpg"/> </div>
|
||||
|
||||
- ServerSocket:服务器端类
|
||||
- Socket:客户端类
|
||||
@@ -208,23 +208,23 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
|
||||
|
||||
1\. 新建一个大小为 8 个字节的缓冲区,此时 position 为 0,而 limit == capacity == 9。capacity 变量不会改变,下面的讨论会忽略它。
|
||||
|
||||
<br><div align="center"> <img src="../pics//1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png"/> </div>
|
||||
|
||||
2\. 从输入通道中读取 3 个字节数据写入缓冲区中,此时 position 移动设为 3,limit 保持不变。
|
||||
|
||||
<br><div align="center"> <img src="../pics//4628274c-25b6-4053-97cf-d1239b44c43d.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//4628274c-25b6-4053-97cf-d1239b44c43d.png"/> </div>
|
||||
|
||||
3\. 在将缓冲区的数据写到输出通道之前,需要先调用 flip() 方法,这个方法将 limit 设置为当前 position,并将 position 设置为 0。
|
||||
|
||||
<br><div align="center"> <img src="../pics//952e06bd-5a65-4cab-82e4-dd1536462f38.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//952e06bd-5a65-4cab-82e4-dd1536462f38.png"/> </div>
|
||||
|
||||
4\. 从缓冲区中取 4 个字节到输出缓冲中,此时 position 设为 4。
|
||||
|
||||
<br><div align="center"> <img src="../pics//b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png"/> </div>
|
||||
|
||||
5\. 最后需要调用 clear() 方法来清空缓冲区,此时 position 和 limit 都被设置为最初位置。
|
||||
|
||||
<br><div align="center"> <img src="../pics//67bf5487-c45d-49b6-b9c0-a058d8c68902.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//67bf5487-c45d-49b6-b9c0-a058d8c68902.png"/> </div>
|
||||
|
||||
## 4. 读写文件实例
|
||||
|
||||
@@ -283,7 +283,7 @@ buffer.clear();
|
||||
|
||||
阻塞式 I/O 在调用 InputStream.read() 方法时会一直等到数据到来时(或超时)才会返回,在调用 ServerSocket.accept() 方法时,也会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。
|
||||
|
||||
<br><div align="center"> <img src="../pics//edc23f99-c46c-4200-b64e-07516828720d.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//edc23f99-c46c-4200-b64e-07516828720d.jpg"/> </div>
|
||||
|
||||
### 5.2 非阻塞式 I/O
|
||||
|
||||
@@ -293,7 +293,7 @@ buffer.clear();
|
||||
|
||||
线程通信:线程之间通过 wait()、notify() 等方式通信,保证每次上下文切换都是有意义的,减少无谓的线程切换。
|
||||
|
||||
<br><div align="center"> <img src="../pics//7fcb2fb0-2cd9-4396-bc2d-282becf963c3.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//7fcb2fb0-2cd9-4396-bc2d-282becf963c3.jpg"/> </div>
|
||||
|
||||
## 6. 套接字实例
|
||||
|
||||
|
||||
+4
-4
@@ -131,13 +131,13 @@ public InitialOrderTest() {
|
||||
|
||||
引用类型引用的是同一个对象,clone() 方法默认就是浅拷贝实现。
|
||||
|
||||
<br><div align="center"> <img src="../pics//d990c0e7-64d1-4ba3-8356-111bc91e53c5.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//d990c0e7-64d1-4ba3-8356-111bc91e53c5.png"/> </div>
|
||||
|
||||
**深拷贝**
|
||||
|
||||
可以使用序列化实现。
|
||||
|
||||
<br><div align="center"> <img src="../pics//2e5620c4-b558-46fe-8f12-00c9dd597a61.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2e5620c4-b558-46fe-8f12-00c9dd597a61.png"/> </div>
|
||||
|
||||
> [How do I copy an object in Java?](https://stackoverflow.com/questions/869033/how-do-i-copy-an-object-in-java)
|
||||
|
||||
@@ -235,7 +235,7 @@ StringBuilder 不是线程安全的;StringBuffer 是线程安全的,使用 s
|
||||
|
||||
如果 String 已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。
|
||||
|
||||
<br><div align="center"> <img src="../pics//f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f76067a5-7d5f-4135-9549-8199c77d8f1c.jpg"/> </div>
|
||||
|
||||
**安全性**
|
||||
|
||||
@@ -381,7 +381,7 @@ Throwable 可以用来表示任何可以作为异常抛出的类,分为两种
|
||||
|
||||
Exception 分为两种: **受检异常** 和 **非受检异常**。受检异常需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;非受检异常是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序奔溃并且无法恢复。
|
||||
|
||||
<br><div align="center"> <img src="../pics//48f8f98e-8dfd-450d-8b5b-df4688f0d377.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//48f8f98e-8dfd-450d-8b5b-df4688f0d377.jpg"/> </div>
|
||||
|
||||
更详细的内容:
|
||||
- [Java 入门之异常处理 ](https://www.tianmaying.com/tutorial/Java-Exception)
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
|
||||
# 概览
|
||||
|
||||
<br><div align="center"> <img src="../pics//ebf03f56-f957-4435-9f8f-0f605661484d.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//ebf03f56-f957-4435-9f8f-0f605661484d.jpg"/> </div>
|
||||
|
||||
容器主要包括 Collection 和 Map 两种,Collection 又包含了 List、Set 以及 Queue。
|
||||
|
||||
|
||||
+1
-1
@@ -347,7 +347,7 @@ JDK 从 1.5 开始在 Thread 类中增添了 State 枚举,包含以下六种
|
||||
5. **TIMED_WAITING** (调用 sleep()、带超时的 wait() 或者 join())
|
||||
6. **TERMINATED** (死亡)
|
||||
|
||||
<br><div align="center"> <img src="../pics//19f2c9ef-6739-4a95-8e9d-aa3f7654e028.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//19f2c9ef-6739-4a95-8e9d-aa3f7654e028.jpg"/> </div>
|
||||
|
||||
# 结束线程
|
||||
|
||||
|
||||
+10
-10
@@ -693,7 +693,7 @@ public List<Integer> topKFrequent(int[] nums, int k) {
|
||||
|
||||
### BFS
|
||||
|
||||
<br><div align="center"> <img src="../pics//4ff355cf-9a7f-4468-af43-e5b02038facc.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//4ff355cf-9a7f-4468-af43-e5b02038facc.jpg"/> </div>
|
||||
|
||||
广度优先搜索的搜索过程有点像一层一层地进行遍历:从节点 0 出发,遍历到 6、2、1 和 5 这四个新节点。
|
||||
|
||||
@@ -750,7 +750,7 @@ private class Position {
|
||||
|
||||
### DFS
|
||||
|
||||
<br><div align="center"> <img src="../pics//f7f7e3e5-7dd4-4173-9999-576b9e2ac0a2.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f7f7e3e5-7dd4-4173-9999-576b9e2ac0a2.png"/> </div>
|
||||
|
||||
广度优先搜索一层一层遍历,每一层遍历到的所有新节点,要用队列先存储起来以备下一层遍历的时候再遍历;而深度优先搜索在遍历到一个新节点时立马对新节点进行遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4;如此反复以这种方式遍历新节点,直到没有新节点了,此时返回。返回到根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2,然后继续以上步骤。
|
||||
|
||||
@@ -1036,7 +1036,7 @@ private void dfs(int r, int c, boolean[][] canReach) {
|
||||
|
||||
[Leetcode : 51. N-Queens (Hard)](https://leetcode.com/problems/n-queens/description/)
|
||||
|
||||
<br><div align="center"> <img src="../pics//1f080e53-4758-406c-bb5f-dbedf89b63ce.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1f080e53-4758-406c-bb5f-dbedf89b63ce.jpg"/> </div>
|
||||
|
||||
题目描述:在 n\*n 的矩阵中摆放 n 个皇后,并且每个皇后不能在同一行,同一列,同一对角线上,要求解所有的 n 皇后解。
|
||||
|
||||
@@ -1044,11 +1044,11 @@ private void dfs(int r, int c, boolean[][] canReach) {
|
||||
|
||||
45 度对角线标记数组的维度为 2\*n - 1,通过下图可以明确 (r,c) 的位置所在的数组下标为 r + c。
|
||||
|
||||
<br><div align="center"> <img src="../pics//85583359-1b45-45f2-9811-4f7bb9a64db7.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//85583359-1b45-45f2-9811-4f7bb9a64db7.jpg"/> </div>
|
||||
|
||||
135 度对角线标记数组的维度也是 2\*n - 1,(r,c) 的位置所在的数组下标为 n - 1 - (r - c)。
|
||||
|
||||
<br><div align="center"> <img src="../pics//9e80f75a-b12b-4344-80c8-1f9ccc2d5246.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//9e80f75a-b12b-4344-80c8-1f9ccc2d5246.jpg"/> </div>
|
||||
|
||||
```java
|
||||
private List<List<String>> ret;
|
||||
@@ -1105,7 +1105,7 @@ private void backstracking(int row) {
|
||||
|
||||
[Leetcode : 17. Letter Combinations of a Phone Number (Medium)](https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/)
|
||||
|
||||
<br><div align="center"> <img src="../pics//a3f34241-bb80-4879-8ec9-dff2d81b514e.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//a3f34241-bb80-4879-8ec9-dff2d81b514e.jpg"/> </div>
|
||||
|
||||
```html
|
||||
Input:Digit string "23"
|
||||
@@ -1547,7 +1547,7 @@ private boolean isPalindrome(String s, int begin, int end) {
|
||||
|
||||
[Leetcode : 37. Sudoku Solver (Hard)](https://leetcode.com/problems/sudoku-solver/description/)
|
||||
|
||||
<br><div align="center"> <img src="../pics//1ca52246-c443-48ae-b1f8-1cafc09ec75c.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1ca52246-c443-48ae-b1f8-1cafc09ec75c.png"/> </div>
|
||||
|
||||
```java
|
||||
private boolean[][] rowsUsed = new boolean[9][10];
|
||||
@@ -2471,7 +2471,7 @@ public int minDistance(String word1, String word2) {
|
||||
|
||||
题目描述:交易之后需要有一天的冷却时间。
|
||||
|
||||
<br><div align="center"> <img src="../pics//ac9b31ec-cef1-4880-a875-fc4571ca10e1.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//ac9b31ec-cef1-4880-a875-fc4571ca10e1.png"/> </div>
|
||||
|
||||
```html
|
||||
s0[i] = max(s0[i - 1], s2[i - 1]); // Stay at s0, or rest from s2
|
||||
@@ -3768,7 +3768,7 @@ private boolean isEqual(ListNode l1, ListNode l2){
|
||||
|
||||
[编程之美:3.4]()
|
||||
|
||||
<br><div align="center"> <img src="../pics//2c968ec5-0967-49ce-ac06-f8f5c9ab33bc.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2c968ec5-0967-49ce-ac06-f8f5c9ab33bc.jpg"/> </div>
|
||||
|
||||
```java
|
||||
B.val = C.val;
|
||||
@@ -4484,7 +4484,7 @@ private void inorder(TreeNode node, int k) {
|
||||
|
||||
### Trie
|
||||
|
||||
<br><div align="center"> <img src="../pics//5c638d59-d4ae-4ba4-ad44-80bdc30f38dd.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//5c638d59-d4ae-4ba4-ad44-80bdc30f38dd.jpg"/> </div>
|
||||
|
||||
Trie,又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种字符串前缀。
|
||||
|
||||
|
||||
+8
-8
@@ -221,7 +221,7 @@ GPT 第 1 个区块记录了 MBR,紧接着是 33 个区块记录分区信息
|
||||
|
||||
GPT 没有扩展分区概念,都是主分区,最多可以分 128 个分区。
|
||||
|
||||
<br><div align="center"> <img src="../pics//a5c25452-6fa5-49e7-9322-823077442775.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//a5c25452-6fa5-49e7-9322-823077442775.jpg"/> </div>
|
||||
|
||||
## 开机检测程序
|
||||
|
||||
@@ -231,7 +231,7 @@ BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可
|
||||
|
||||
MBR 中的开机管理程序提供以下功能:选单、载入核心文件以及转交其它开机管理程序。转交这个功能可以用来实现了多重引导,只需要将另一个操作系统的开机管理程序安装在其它分区的启动扇区上,在启动 MBR 中的开机管理程序时,就可以选择启动当前的操作系统或者转交给其它开机管理程序从而启动另一个操作系统。
|
||||
|
||||
<br><div align="center"> <img src="../pics//f900f266-a323-42b2-bc43-218fdb8811a8.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f900f266-a323-42b2-bc43-218fdb8811a8.jpg"/> </div>
|
||||
|
||||
安装多重引导,最好先安装 Windows 再安装 Linux。因为安装 Windows 时会覆盖掉 MBR,而 Linux 可以选择将开机管理程序安装在 MBR 或者其它分区的启动扇区,并且可以设置开机管理程序的选单。
|
||||
|
||||
@@ -243,7 +243,7 @@ UEFI 相比于 BIOS 来说功能更为全面,也更为安全。
|
||||
|
||||
挂载利用目录作为分区的进入点,也就是说,进入目录之后就可以读取分区的数据。
|
||||
|
||||
<br><div align="center"> <img src="../pics//249f3bb1-feee-4805-a259-a72699d638ca.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//249f3bb1-feee-4805-a259-a72699d638ca.jpg"/> </div>
|
||||
|
||||
# 文件权限与目录配置
|
||||
|
||||
@@ -342,7 +342,7 @@ UEFI 相比于 BIOS 来说功能更为全面,也更为安全。
|
||||
|
||||
完整的目录树如下:
|
||||
|
||||
<br><div align="center"> <img src="../pics//27ace615-558f-4dfb-8ad4-7ac769c10118.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//27ace615-558f-4dfb-8ad4-7ac769c10118.jpg"/> </div>
|
||||
|
||||
# 文件与目录
|
||||
|
||||
@@ -503,7 +503,7 @@ find 可以使用文件的属性和权限进行搜索。
|
||||
|
||||
+4、4 和 -4 的指示的时间范围如下:
|
||||
|
||||
<br><div align="center"> <img src="../pics//658fc5e7-79c0-4247-9445-d69bf194c539.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//658fc5e7-79c0-4247-9445-d69bf194c539.png"/> </div>
|
||||
|
||||
#### 4.2 与文件拥有者和所属群组有关的选项
|
||||
|
||||
@@ -545,7 +545,7 @@ find 可以使用文件的属性和权限进行搜索。
|
||||
|
||||
Ext2 文件系统使用了上述的文件结构,并在此之上加入了 block 群组的概念,也就是将一个文件系统划分为多个 block 群组,方便管理。
|
||||
|
||||
<br><div align="center"> <img src="../pics//1974a836-aa6b-4fb8-bce1-6eb11969284a.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1974a836-aa6b-4fb8-bce1-6eb11969284a.jpg"/> </div>
|
||||
|
||||
## inode
|
||||
|
||||
@@ -553,7 +553,7 @@ Ext2 文件系统支持的 block 大小有 1k、2k 和 4k 三种,不同的 blo
|
||||
|
||||
inode 中记录了文件内容所在的 block,但是每个 block 非常小,一个大文件随便都需要几十万的 block,而一个 inode 大小有限,无法直接引用这么多 block。因此引入了间接、双间接、三间接引用。间接引用是指,让 inode 记录的引用 block 块当成 inode 用来记录引用信息。
|
||||
|
||||
<br><div align="center"> <img src="../pics//89091427-7b2b-4923-aff6-44681319a8aa.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//89091427-7b2b-4923-aff6-44681319a8aa.jpg"/> </div>
|
||||
|
||||
inode 具体包含以下信息:
|
||||
|
||||
@@ -1031,7 +1031,7 @@ daemon 2
|
||||
|
||||
# vim 三个模式
|
||||
|
||||
<br><div align="center"> <img src="../pics//341c632a-1fc1-4068-9b9f-bf7ef68ebb4c.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//341c632a-1fc1-4068-9b9f-bf7ef68ebb4c.jpg"/> </div>
|
||||
|
||||
在指令列模式下,有以下命令用于离开或者存储文件。
|
||||
|
||||
|
||||
+5
-5
@@ -238,7 +238,7 @@ customer_id_selectivity: 0.0373
|
||||
|
||||
### 3.5 聚簇索引
|
||||
|
||||
<br><div align="center"> <img src="../pics//b9e9ae8c-e216-4c01-b267-a50dbeb98fa4.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//b9e9ae8c-e216-4c01-b267-a50dbeb98fa4.jpg"/> </div>
|
||||
|
||||
聚簇索引并不是一种索引类型,而是一种数据存储方式。
|
||||
|
||||
@@ -267,7 +267,7 @@ customer_id_selectivity: 0.0373
|
||||
|
||||
### 4. 1 B-Tree
|
||||
|
||||
<br><div align="center"> <img src="../pics//5ed71283-a070-4b21-85ae-f2cbfd6ba6e1.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//5ed71283-a070-4b21-85ae-f2cbfd6ba6e1.jpg"/> </div>
|
||||
|
||||
为了描述 B-Tree,首先定义一条数据记录为一个二元组 [key, data],key 为记录的键,data 为数据记录除 key 外的数据。
|
||||
|
||||
@@ -283,7 +283,7 @@ B-Tree 是满足下列条件的数据结构:
|
||||
|
||||
### 4.2 B+Tree
|
||||
|
||||
<br><div align="center"> <img src="../pics//63cd5b50-d6d8-4df6-8912-ef4a1dd5ba13.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//63cd5b50-d6d8-4df6-8912-ef4a1dd5ba13.jpg"/> </div>
|
||||
|
||||
与 B-Tree 相比,B+Tree 有以下不同点:
|
||||
|
||||
@@ -292,7 +292,7 @@ B-Tree 是满足下列条件的数据结构:
|
||||
|
||||
### 4.3 带有顺序访问指针的 B+Tree
|
||||
|
||||
<br><div align="center"> <img src="../pics//1ee5f0a5-b8df-43b9-95ab-c516c54ec797.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1ee5f0a5-b8df-43b9-95ab-c516c54ec797.jpg"/> </div>
|
||||
|
||||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 基础上进行了优化,在叶子节点增加了顺序访问指针,做这个优化的目的是为了提高区间访问的性能。
|
||||
|
||||
@@ -405,7 +405,7 @@ do {
|
||||
|
||||
通过代理,可以路由流量到可以使用的服务器上。
|
||||
|
||||
<br><div align="center"> <img src="../pics//fabd5fa0-b75e-48d0-9e2c-31471945ceb9.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//fabd5fa0-b75e-48d0-9e2c-31471945ceb9.jpg"/> </div>
|
||||
|
||||
**1.4 在应用中处理故障转移**
|
||||
|
||||
|
||||
+1
-1
@@ -710,7 +710,7 @@ SHOW GRANTS FOR myuser;
|
||||
GRANT SELECT, INSERT ON mydatabase.* TO myuser;
|
||||
```
|
||||
|
||||
<br><div align="center"> <img src="../pics//c73aa08e-a987-43c9-92be-adea4a884c25.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c73aa08e-a987-43c9-92be-adea4a884c25.png"/> </div>
|
||||
|
||||
账户用 username@host 的形式定义,username@% 使用的是默认主机名。
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@
|
||||
|
||||
用 min、max 表示数量范围;用 first、last 表示访问空间的包含范围,begin、end 表示访问空间的排除范围,即 end 不包含尾部。
|
||||
|
||||
<br><div align="center"> <img src="../pics//05907ab4-42c5-4b5e-9388-6617f6c97bea.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//05907ab4-42c5-4b5e-9388-6617f6c97bea.jpg"/> </div>
|
||||
|
||||
布尔相关的命名加上 is、can、should、has 等前缀。
|
||||
|
||||
|
||||
@@ -287,7 +287,7 @@ private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int[] in,
|
||||
- 如果一个节点有右子树不为空,那么该节点的下一个节点是右子树的最左节点;
|
||||
- 否则,向上找第一个左链接指向的树包含该节点的祖先节点。
|
||||
|
||||
<br><div align="center"> <img src="../pics//6fec7f56-a685-4232-b03e-c92a8dfba486.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//6fec7f56-a685-4232-b03e-c92a8dfba486.png"/> </div>
|
||||
|
||||
```java
|
||||
public TreeLinkNode GetNext(TreeLinkNode pNode) {
|
||||
@@ -1077,15 +1077,15 @@ private void dfs(TreeNode node, int target, int curSum, ArrayList<Integer> path)
|
||||
|
||||
第一步,在每个节点的后面插入复制的节点。
|
||||
|
||||
<br><div align="center"> <img src="../pics//f8b12555-967b-423d-a84e-bc9eff104b8b.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f8b12555-967b-423d-a84e-bc9eff104b8b.jpg"/> </div>
|
||||
|
||||
第二步,对复制节点的 random 链接进行赋值。
|
||||
|
||||
<br><div align="center"> <img src="../pics//7b877a2a-8fd1-40d8-a34c-c445827300b8.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//7b877a2a-8fd1-40d8-a34c-c445827300b8.jpg"/> </div>
|
||||
|
||||
第三步,拆分。
|
||||
|
||||
<br><div align="center"> <img src="../pics//b2b6253c-c701-4b30-aff4-bc3c713542a7.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//b2b6253c-c701-4b30-aff4-bc3c713542a7.jpg"/> </div>
|
||||
|
||||
|
||||
```java
|
||||
|
||||
+41
-41
File diff suppressed because it is too large
Load Diff
+11
-11
@@ -169,7 +169,7 @@
|
||||
|
||||
## 进程状态的切换
|
||||
|
||||
<br><div align="center"> <img src="../pics//1706ce58-a081-4fed-9b36-c3c0d7e22b3a.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1706ce58-a081-4fed-9b36-c3c0d7e22b3a.jpg"/> </div>
|
||||
|
||||
阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU,缺少 CPU 会让进程从运行态转换为就绪态。
|
||||
|
||||
@@ -219,7 +219,7 @@ shortest remaining time next(SRTN)。
|
||||
|
||||
#### 2.3 多级反馈队列
|
||||
|
||||
<br><div align="center"> <img src="../pics//042cf928-3c8e-4815-ae9c-f2780202c68f.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//042cf928-3c8e-4815-ae9c-f2780202c68f.png"/> </div>
|
||||
|
||||
1. 设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权越高的队列中,为每个进程所规定的执行时间片就越小。
|
||||
|
||||
@@ -470,7 +470,7 @@ void writer() {
|
||||
|
||||
### 2. 哲学家进餐问题
|
||||
|
||||
<br><div align="center"> <img src="../pics//a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//a9077f06-7584-4f2b-8c20-3a8e46928820.jpg"/> </div>
|
||||
|
||||
五个哲学家围着一张圆周,每个哲学家面前放着饭。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先一根一根拿起左右两边的筷子。
|
||||
|
||||
@@ -520,7 +520,7 @@ void philosopher(int i) {
|
||||
|
||||
## 死锁的条件
|
||||
|
||||
<br><div align="center"> <img src="../pics//c037c901-7eae-4e31-a1e4-9d41329e5c3e.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c037c901-7eae-4e31-a1e4-9d41329e5c3e.png"/> </div>
|
||||
|
||||
1. 互斥
|
||||
2. 请求与保持
|
||||
@@ -561,7 +561,7 @@ void philosopher(int i) {
|
||||
|
||||
#### 3.1 安全状态
|
||||
|
||||
<br><div align="center"> <img src="../pics//ed523051-608f-4c3f-b343-383e2d194470.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//ed523051-608f-4c3f-b343-383e2d194470.png"/> </div>
|
||||
|
||||
图 a 的第二列 has 表示已拥有的资源数,第三列 max 表示总共需要的资源数,free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源,运行结束后释放 B,此时 free 变为 4;接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
|
||||
|
||||
@@ -571,13 +571,13 @@ void philosopher(int i) {
|
||||
|
||||
一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。
|
||||
|
||||
<br><div align="center"> <img src="../pics//d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//d160ec2e-cfe2-4640-bda7-62f53e58b8c0.png"/> </div>
|
||||
|
||||
上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。
|
||||
|
||||
#### 3.3 多个资源的银行家算法
|
||||
|
||||
<br><div align="center"> <img src="../pics//62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//62e0dd4f-44c3-43ee-bb6e-fedb9e068519.png"/> </div>
|
||||
|
||||
上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。
|
||||
|
||||
@@ -595,7 +595,7 @@ void philosopher(int i) {
|
||||
|
||||
死锁检测的基本思想是,如果一个进程所请求的资源能够被满足,那么就让它执行,释放它拥有的所有资源,然后让其它能满足条件的进程执行。
|
||||
|
||||
<br><div align="center"> <img src="../pics//e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//e1eda3d5-5ec8-4708-8e25-1a04c5e11f48.png"/> </div>
|
||||
|
||||
上图中,有三个进程四个资源,每个数据代表的含义如下:
|
||||
|
||||
@@ -635,11 +635,11 @@ void philosopher(int i) {
|
||||
|
||||
### 2. 分段
|
||||
|
||||
<br><div align="center"> <img src="../pics//22de0538-7c6e-4365-bd3b-8ce3c5900216.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//22de0538-7c6e-4365-bd3b-8ce3c5900216.png"/> </div>
|
||||
|
||||
上图为一个编译器在编译过程中建立的多个表,有 4 个表是动态增长的,如果使用分页系统的一维地址空间,动态递增的特点会导致覆盖问题的出现。
|
||||
|
||||
<br><div align="center"> <img src="../pics//e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//e0900bb2-220a-43b7-9aa9-1d5cd55ff56e.png"/> </div>
|
||||
|
||||
分段的做法是把每个表分成段,一个段构成一个独立的地址空间。每个段的长度可以不同,并且可以动态增长。
|
||||
|
||||
@@ -693,7 +693,7 @@ void philosopher(int i) {
|
||||
|
||||
4,7,0,7,1,0,1,2,1,2,6
|
||||
|
||||
<br><div align="center"> <img src="../pics//eb859228-c0f2-4bce-910d-d9f76929352b.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//eb859228-c0f2-4bce-910d-d9f76929352b.png"/> </div>
|
||||
|
||||
### 4. 时钟(Clock)
|
||||
|
||||
|
||||
+58
-58
File diff suppressed because it is too large
Load Diff
+42
-42
File diff suppressed because it is too large
Load Diff
+12
-12
@@ -124,7 +124,7 @@
|
||||
|
||||
包括三个类:Movie、Rental 和 Customer,Rental 包含租赁的 Movie 以及天数。
|
||||
|
||||
<br><div align="center"> <img src="../pics//25d6d3d4-4726-47b1-a9cb-3316d1ff5dd5.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//25d6d3d4-4726-47b1-a9cb-3316d1ff5dd5.png"/> </div>
|
||||
|
||||
最开始的实现是把所有的计费代码都放在 Customer 类中。
|
||||
|
||||
@@ -159,19 +159,19 @@ double getTotalCharge() {
|
||||
|
||||
以下是继承 Movie 的多态解决方案,这种方案可以解决上述的 switch 问题,因为每种电影类别的计费方式都被放到了对应 Movie 子类中,当变化发生时,只需要去修改对应子类中的代码即可。
|
||||
|
||||
<br><div align="center"> <img src="../pics//76b48b4c-8999-4967-893b-832602e73285.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//76b48b4c-8999-4967-893b-832602e73285.png"/> </div>
|
||||
|
||||
但是由于 Movie 可以在其生命周期内修改自己的类别,一个对象却不能在生命周期内修改自己所属的类,因此这种方案不可行。可以使用策略模式来解决这个问题(原书写的是使用状态模式,但是这里应该为策略模式,具体可以参考设计模式内容)。
|
||||
|
||||
下图中,Price 有多种实现,Movie 组合了一个 Price 对象,并且在运行时可以改变组合的 Price 对象,从而使得它的计费方式发生改变。
|
||||
|
||||
<br><div align="center"> <img src="../pics//2a842a14-e4ab-4f37-83fa-f82c206fe426.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2a842a14-e4ab-4f37-83fa-f82c206fe426.png"/> </div>
|
||||
|
||||
重构后整体的类图和时序图如下:
|
||||
|
||||
<br><div align="center"> <img src="../pics//9d549816-60b7-4899-9877-23b01503ab13.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//9d549816-60b7-4899-9877-23b01503ab13.png"/> </div>
|
||||
|
||||
<br><div align="center"> <img src="../pics//2c8a7a87-1bf1-4d66-9ba9-225a1add0a51.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//2c8a7a87-1bf1-4d66-9ba9-225a1add0a51.png"/> </div>
|
||||
|
||||
# 重构原则
|
||||
|
||||
@@ -579,7 +579,7 @@ Hide Delegate 有很大好处,但是它的代价是:每当客户要使用受
|
||||
|
||||
将该数据赋值到一个领域对象中,建立一个 Oberver 模式,用以同步领域对象和 GUI 对象内的重复数据。
|
||||
|
||||
<br><div align="center"> <img src="../pics//e024bd7e-fb4e-4239-9451-9a6227f50b00.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//e024bd7e-fb4e-4239-9451-9a6227f50b00.jpg"/> </div>
|
||||
|
||||
## 7. Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
|
||||
|
||||
@@ -636,13 +636,13 @@ public 字段应当改为 private,并提供相应的访问函数。
|
||||
|
||||
类中有一个数值类型码,但它并不影响类的行为,就用一个新类替换该数值类型码。如果类型码出现在 switch 语句中,需要使用 Replace Conditional with Polymorphism 去掉 switch,首先必须运用 Replace Type Code with Subcalss 或 Replace Type Code with State/Strategy 去掉类型码。
|
||||
|
||||
<br><div align="center"> <img src="../pics//27c2e0b3-8f95-453d-bedc-6398a8566ce9.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//27c2e0b3-8f95-453d-bedc-6398a8566ce9.jpg"/> </div>
|
||||
|
||||
## 14. Replace Type Code with Subcalsses(以子类取代类型码)
|
||||
|
||||
有一个不可变的类型码,它会影响类的行为,以子类取代这个类型码。
|
||||
|
||||
<br><div align="center"> <img src="../pics//c41d3977-e0e7-4ee4-93e1-d84f1ae3e20e.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//c41d3977-e0e7-4ee4-93e1-d84f1ae3e20e.jpg"/> </div>
|
||||
|
||||
## 15. Replace Type Code with State/Strategy (以 State/Strategy 取代类型码)
|
||||
|
||||
@@ -650,13 +650,13 @@ public 字段应当改为 private,并提供相应的访问函数。
|
||||
|
||||
和 Replace Type Code with Subcalsses 的区别是 Replace Type Code with State/Strategy 的类型码是动态可变的,前者通过继承的方式来实现,后者通过组合的方式来实现。因为类型码可变,如果通过继承的方式,一旦一个对象的类型码改变,那么就要改变用新的对象来取代旧对象,而客户端难以改变新的对象。但是通过组合的方式,改变引用的状态类是很容易的。
|
||||
|
||||
<br><div align="center"> <img src="../pics//81fd1d6f-a3b2-4160-9a0a-1f7cb50ba440.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//81fd1d6f-a3b2-4160-9a0a-1f7cb50ba440.jpg"/> </div>
|
||||
|
||||
## 16. Replace Subclass with Fields(以字段取代子类)
|
||||
|
||||
各个子类的唯一差别只在“返回常量数据”的函数上。
|
||||
|
||||
<br><div align="center"> <img src="../pics//f2e0cee9-ecdc-4a96-853f-d9f6a1ad6ad1.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//f2e0cee9-ecdc-4a96-853f-d9f6a1ad6ad1.jpg"/> </div>
|
||||
|
||||
# 简化条件表达式
|
||||
|
||||
@@ -776,7 +776,7 @@ double getSpeed() {
|
||||
}
|
||||
```
|
||||
|
||||
<br><div align="center"> <img src="../pics//1c8432c8-2552-457f-b117-1da36c697221.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//1c8432c8-2552-457f-b117-1da36c697221.jpg"/> </div>
|
||||
|
||||
## 7. Introduce Null Object(引入Null对象)
|
||||
|
||||
@@ -916,7 +916,7 @@ double finalPrice = discountedPrice (basePrice);
|
||||
|
||||
以一个对象取代这些参数。
|
||||
|
||||
<br><div align="center"> <img src="../pics//08738dd0-ae8e-404a-ba78-a6b1b7d225b3.jpg"/> </div><br>
|
||||
<div align="center"> <img src="../pics//08738dd0-ae8e-404a-ba78-a6b1b7d225b3.jpg"/> </div>
|
||||
|
||||
## 10. Remove Setting Method(移除设值函数)
|
||||
|
||||
|
||||
+13
-13
@@ -197,13 +197,13 @@ public class Music {
|
||||
|
||||
从具体类中继承
|
||||
|
||||
<br><div align="center"> <img src="../pics//29badd92-109f-4f29-abb9-9857f5973928.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//29badd92-109f-4f29-abb9-9857f5973928.png"/> </div>
|
||||
|
||||
② 实现关系 (realize)
|
||||
|
||||
从抽象类或者接口中继承
|
||||
|
||||
<br><div align="center"> <img src="../pics//4b16e1d3-3a60-472c-9756-2f31b1c48abe.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//4b16e1d3-3a60-472c-9756-2f31b1c48abe.png"/> </div>
|
||||
|
||||
**1.2 整体和部分**
|
||||
|
||||
@@ -211,13 +211,13 @@ public class Music {
|
||||
|
||||
表示整体由部分组成,但是整体和部分不是强依赖的,整体不存在了部分还是会存在。以下表示 B 由 A 组成:
|
||||
|
||||
<br><div align="center"> <img src="../pics//34259bb8-ca3a-4872-8771-9e946782d9c3.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//34259bb8-ca3a-4872-8771-9e946782d9c3.png"/> </div>
|
||||
|
||||
② 组合关系 (composition)
|
||||
|
||||
和聚合不同,组合中整体和部分是强依赖的,整体不存在了部分也不存在了。比如公司和部门,公司没了部门就不存在了。但是公司和员工就属于聚合关系了,因为公司没了员工还在。
|
||||
|
||||
<br><div align="center"> <img src="../pics//7dda050d-ac35-4f47-9f51-18f18ed6fa9a.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//7dda050d-ac35-4f47-9f51-18f18ed6fa9a.png"/> </div>
|
||||
|
||||
**1.3 相互联系**
|
||||
|
||||
@@ -225,13 +225,13 @@ public class Music {
|
||||
|
||||
表示不同类对象之间有关联,这是一种静态关系,与运行过程的状态无关,在最开始就可以确定。因此也可以用 1 对 1、多对 1、多对多这种关联关系来表示。比如学生和学校就是一种关联关系,一个学校可以有很多学生,但是一个学生只属于一个学校,因此这是一种多对一的关系,在运行开始之前就可以确定。
|
||||
|
||||
<br><div align="center"> <img src="../pics//4ccd294c-d6b2-421b-839e-d88336ff5fb7.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//4ccd294c-d6b2-421b-839e-d88336ff5fb7.png"/> </div>
|
||||
|
||||
② 依赖关系 (dependency)
|
||||
|
||||
和关联关系不同的是 , 依赖关系是在运行过程中起作用的。一般依赖作为类的构造器或者方法的参数传入。双向依赖时一种不好的设计。
|
||||
|
||||
<br><div align="center"> <img src="../pics//47ca2614-509f-476e-98fc-50ec9f9d43c0.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//47ca2614-509f-476e-98fc-50ec9f9d43c0.png"/> </div>
|
||||
|
||||
## 2. 时序图
|
||||
|
||||
@@ -245,7 +245,7 @@ http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html
|
||||
|
||||
从虚线从上往下表示时间的推进。
|
||||
|
||||
<br><div align="center"> <img src="../pics//80c5aff8-fc46-4810-aeaa-215b5c60a003.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//80c5aff8-fc46-4810-aeaa-215b5c60a003.png"/> </div>
|
||||
|
||||
可见,通过时序图可以知道每个类具有以下操作:
|
||||
|
||||
@@ -289,7 +289,7 @@ public class 孙权 {
|
||||
|
||||
有三种表现形式
|
||||
|
||||
<br><div align="center"> <img src="../pics//25b8adad-2ef6-4f30-9012-c306b4e49897.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//25b8adad-2ef6-4f30-9012-c306b4e49897.png"/> </div>
|
||||
|
||||
在画图时,应该遵循以下原则:
|
||||
|
||||
@@ -301,7 +301,7 @@ public class 孙权 {
|
||||
|
||||
生命线从对象的创建开始到对象销毁时终止
|
||||
|
||||
<br><div align="center"> <img src="../pics//b7b0eac6-e7ea-4fb6-8bfb-95fec6f235e2.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//b7b0eac6-e7ea-4fb6-8bfb-95fec6f235e2.png"/> </div>
|
||||
|
||||
③ 消息
|
||||
|
||||
@@ -311,15 +311,15 @@ public class 孙权 {
|
||||
|
||||
1\. 简单消息,不区分同步异步。
|
||||
|
||||
<br><div align="center"> <img src="../pics//a13b62da-0fa8-4224-a615-4cadacc08871.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//a13b62da-0fa8-4224-a615-4cadacc08871.png"/> </div>
|
||||
|
||||
2\. 同步消息,发送消息之后需要暂停活动来等待回应。
|
||||
|
||||
<br><div align="center"> <img src="../pics//33821037-dc40-4266-901c-e5b38e618426.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//33821037-dc40-4266-901c-e5b38e618426.png"/> </div>
|
||||
|
||||
3\. 异步消息,发送消息之后不需要等待。
|
||||
|
||||
<br><div align="center"> <img src="../pics//dec6c6cc-1b5f-44ed-b8fd-464fcf849dac.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//dec6c6cc-1b5f-44ed-b8fd-464fcf849dac.png"/> </div>
|
||||
|
||||
4\. 返回消息,可选。
|
||||
|
||||
@@ -327,7 +327,7 @@ public class 孙权 {
|
||||
|
||||
生命线上的方框表示激活状态,其它时间处于休眠状态。
|
||||
|
||||
<br><div align="center"> <img src="../pics//6ab5de9b-1c1e-4118-b2c3-fb6c7ed7de6f.png"/> </div><br>
|
||||
<div align="center"> <img src="../pics//6ab5de9b-1c1e-4118-b2c3-fb6c7ed7de6f.png"/> </div>
|
||||
|
||||
|
||||
# 参考资料
|
||||
|
||||
Reference in New Issue
Block a user