auto commit
This commit is contained in:
@ -1,33 +1,34 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [ǰ<EFBFBD><EFBFBD>](#ǰ<EFBFBD><EFBFBD>)
|
||||
* [1. С<EFBFBD><EFBFBD>-С<><D0A1>Git](#1-С<EFBFBD><EFBFBD>-С<><D0A1>git)
|
||||
* [2. С<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#2-С<><D0A1>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. С<EFBFBD><EFBFBD>-<2D>й<EFBFBD>ţ<EFBFBD><C5A3>](#3-С<><D0A1>-<2D>й<EFBFBD>ţ<EFBFBD><C5A3>)
|
||||
* [4. <EFBFBD><EFBFBD>-LUCKY STRING](#4-<EFBFBD><EFBFBD>-lucky-string)
|
||||
* [5. <EFBFBD><EFBFBD>-Numeric Keypad](#5-<EFBFBD><EFBFBD>-numeric-keypad)
|
||||
* [6. <EFBFBD><EFBFBD>-Spring Outing](#6-<EFBFBD><EFBFBD>-spring-outing)
|
||||
* [7. <EFBFBD><EFBFBD>-S-expression](#7-<EFBFBD><EFBFBD>-s-expression)
|
||||
* [8. <EFBFBD><EFBFBD>Ϊ-<2D><><EFBFBD>߷<EFBFBD><DFB7>Ƕ<EFBFBD><C7B6><EFBFBD>](#8-<2D><>Ϊ-<2D><><EFBFBD>߷<EFBFBD><DFB7>Ƕ<EFBFBD><C7B6><EFBFBD>)
|
||||
* [9. <EFBFBD><EFBFBD>Ϊ-<2D><EFBFBD><F2B5A5B4><EFBFBD><EFBFBD><EFBFBD>¼](#9-<2D><>Ϊ-<2D><EFBFBD><F2B5A5B4><EFBFBD><EFBFBD><EFBFBD>¼)
|
||||
* [10. <EFBFBD><EFBFBD>Ϊ-<2D>˿<EFBFBD><CBBF>ƴ<EFBFBD>С](#10-<2D><>Ϊ-<2D>˿<EFBFBD><CBBF>ƴ<EFBFBD>С)
|
||||
* [11. ȥ<EFBFBD>Ķ<EFBFBD>-<2D><><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>](#11-ȥ<>Ķ<EFBFBD>-<2D><><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>)
|
||||
* [12. ȥ<EFBFBD>Ķ<EFBFBD>-<2D><EFBFBD><D7B8>ظ<EFBFBD><D8B8>ַ<EFBFBD>](#12-ȥ<>Ķ<EFBFBD>-<2D><EFBFBD><D7B8>ظ<EFBFBD><D8B8>ַ<EFBFBD>)
|
||||
* [13. ȥ<EFBFBD>Ķ<EFBFBD>-Ѱ<><D1B0>Coder](#13-ȥ<EFBFBD>Ķ<EFBFBD>-Ѱ<><D1B0>coder)
|
||||
* [14. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ](#14-<2D><><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ)
|
||||
* [15. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD>ӷ<EFBFBD>ת](#15-<2D><><EFBFBD><EFBFBD>-<2D><><EFBFBD>ӷ<EFBFBD>ת)
|
||||
* [16. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>ݷ<EFBFBD>](#16-<2D><><EFBFBD><EFBFBD>-<2D>ݷ<EFBFBD>)
|
||||
* [17. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-ֱ<><D6B1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#17-<2D><><EFBFBD><EFBFBD>-ֱ<><D6B1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [18. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#18-<2D><><EFBFBD><EFBFBD>-<2D>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [19. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-ƽ<><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#19-<2D><><EFBFBD><EFBFBD>-ƽ<><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [20. <EFBFBD>ٶ<EFBFBD>-<2D>ﷸת<EFB7B8><D7AA>](#20-<2D>ٶ<EFBFBD>-<2D>ﷸת<EFB7B8><D7AA>)
|
||||
* [22. <EFBFBD>ٶ<EFBFBD>-<2D>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>ֽ](#22-<2D>ٶ<EFBFBD>-<2D>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>ֽ)
|
||||
* [23. <EFBFBD>ٶ<EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#23-<2D>ٶ<EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [24. <EFBFBD>ٶ<EFBFBD>-Ģ<><C4A2><EFBFBD><EFBFBD>](#24-<2D>ٶ<EFBFBD>-Ģ<><C4A2><EFBFBD><EFBFBD>)
|
||||
* [前言](#前言)
|
||||
* [1. 小米-小米Git](#1-小米-小米git)
|
||||
* [2. 小米-懂二进制](#2-小米-懂二进制)
|
||||
* [3. 小米-中国牛市](#3-小米-中国牛市)
|
||||
* [4. 微软-LUCKY STRING](#4-微软-lucky-string)
|
||||
* [5. 微软-Numeric Keypad](#5-微软-numeric-keypad)
|
||||
* [6. 微软-Spring Outing](#6-微软-spring-outing)
|
||||
* [7. 微软-S-expression](#7-微软-s-expression)
|
||||
* [8. 华为-最高分是多少](#8-华为-最高分是多少)
|
||||
* [9. 华为-简单错误记录](#9-华为-简单错误记录)
|
||||
* [10. 华为-扑克牌大小](#10-华为-扑克牌大小)
|
||||
* [11. 去哪儿-二分查找](#11-去哪儿-二分查找)
|
||||
* [12. 去哪儿-首个重复字符](#12-去哪儿-首个重复字符)
|
||||
* [13. 去哪儿-寻找Coder](#13-去哪儿-寻找coder)
|
||||
* [14. 美团-最大差值](#14-美团-最大差值)
|
||||
* [15. 美团-棋子翻转](#15-美团-棋子翻转)
|
||||
* [16. 美团-拜访](#16-美团-拜访)
|
||||
* [17. 美团-直方图内最大矩形](#17-美团-直方图内最大矩形)
|
||||
* [18. 美团-字符串计数](#18-美团-字符串计数)
|
||||
* [19. 美团-平均年龄](#19-美团-平均年龄)
|
||||
* [20. 百度-罪犯转移](#20-百度-罪犯转移)
|
||||
* [22. 百度-裁减网格纸](#22-百度-裁减网格纸)
|
||||
* [23. 百度-钓鱼比赛](#23-百度-钓鱼比赛)
|
||||
* [24. 百度-蘑菇阵](#24-百度-蘑菇阵)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# ǰ<><C7B0>
|
||||
|
||||
ʡ<EFBFBD>ԵĴ<EFBFBD><EFBFBD>룺
|
||||
# 前言
|
||||
|
||||
省略的代码:
|
||||
|
||||
```java
|
||||
import java.util.*;
|
||||
@ -48,10 +49,10 @@ public class Main {
|
||||
}
|
||||
```
|
||||
|
||||
# 1. С<EFBFBD><EFBFBD>-С<><D0A1>Git
|
||||
# 1. 小米-小米Git
|
||||
|
||||
- <EFBFBD>ؽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- ʹ<EFBFBD><EFBFBD> LCA
|
||||
- 重建多叉树
|
||||
- 使用 LCA
|
||||
|
||||
```java
|
||||
private class TreeNode {
|
||||
@ -65,7 +66,7 @@ private class TreeNode {
|
||||
|
||||
public int getSplitNode(String[] matrix, int indexA, int indexB) {
|
||||
int n = matrix.length;
|
||||
boolean[][] linked = new boolean[n][n]; // <EFBFBD>ؽ<EFBFBD><EFBFBD>ڽӾ<EFBFBD><EFBFBD><EFBFBD>
|
||||
boolean[][] linked = new boolean[n][n]; // 重建邻接矩阵
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
linked[i][j] = matrix[i].charAt(j) == '1';
|
||||
@ -80,7 +81,7 @@ private TreeNode constructTree(boolean[][] linked, int root) {
|
||||
TreeNode tree = new TreeNode(root);
|
||||
for (int i = 0; i < linked[root].length; i++) {
|
||||
if (linked[root][i]) {
|
||||
linked[i][root] = false; // <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽӾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>תΪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
linked[i][root] = false; // 因为题目给的邻接矩阵是双向的,在这里需要把它转为单向的
|
||||
tree.childs.add(constructTree(links, i));
|
||||
}
|
||||
}
|
||||
@ -102,9 +103,9 @@ private TreeNode LCA(TreeNode root, TreeNode p, TreeNode q) {
|
||||
}
|
||||
```
|
||||
|
||||
# 2. С<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 2. 小米-懂二进制
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʊ<EFBFBD>ʾΪ 1 <20><><EFBFBD><EFBFBD>һλ<D2BB><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>λ<EFBFBD><CEBB>
|
||||
对两个数进行异或,结果的二进制表示为 1 的那一位就是两个数不同的位。
|
||||
|
||||
```java
|
||||
public int countBitDiff(int m, int n) {
|
||||
@ -112,11 +113,11 @@ public int countBitDiff(int m, int n) {
|
||||
}
|
||||
```
|
||||
|
||||
# 3. С<EFBFBD><EFBFBD>-<2D>й<EFBFBD>ţ<EFBFBD><C5A3>
|
||||
# 3. 小米-中国牛市
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>СΪ 2 <20>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>
|
||||
背包问题,可以设一个大小为 2 的背包。
|
||||
|
||||
״̬ת<EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
状态转移方程如下:
|
||||
|
||||
```html
|
||||
dp[i, j] = max(dp[i, j-1], prices[j] - prices[jj] + dp[i-1, jj]) { jj in range of [0, j-1] } = max(dp[i, j-1], prices[j] + max(dp[i-1, jj] - prices[jj]))
|
||||
@ -137,10 +138,10 @@ public int calculateMax(int[] prices) {
|
||||
}
|
||||
```
|
||||
|
||||
# 4. <EFBFBD><EFBFBD>-LUCKY STRING
|
||||
# 4. 微软-LUCKY STRING
|
||||
|
||||
- 쳲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD>㣻
|
||||
- <EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>β<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>̣<EFBFBD>ÿһ<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> Set <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> i <EFBFBD><EFBFBD> j <EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Set <20><>֤<EFBFBD><D6A4><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Set <20>Ĵ<EFBFBD>С<EFBFBD><D0A1><EFBFBD>Dz<EFBFBD>ͬ<EFBFBD>ַ<EFBFBD><D6B7>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 斐波那契数列可以预计算;
|
||||
- 从头到尾遍历字符串的过程,每一轮循环都使用一个 Set 来保存从 i 到 j 出现的字符,并且 Set 保证了字符都不同,因此 Set 的大小就是不同字符的个数。
|
||||
|
||||
```java
|
||||
Set<Integer> fibSet = new HashSet<>(Arrays.asList(1, 2, 3, 5, 8, 13, 21, 34, 55, 89));
|
||||
@ -165,7 +166,7 @@ for (String s : arr) {
|
||||
}
|
||||
```
|
||||
|
||||
# 5. <EFBFBD><EFBFBD>-Numeric Keypad
|
||||
# 5. 微软-Numeric Keypad
|
||||
|
||||
```java
|
||||
private static int[][] canReach = {
|
||||
@ -209,17 +210,17 @@ public static void main(String[] args) {
|
||||
}
|
||||
```
|
||||
|
||||
# 6. <EFBFBD><EFBFBD>-Spring Outing
|
||||
# 6. 微软-Spring Outing
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> N = 3<EFBFBD><EFBFBD>K = 4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۡ<EFBFBD>
|
||||
下面以 N = 3,K = 4 来进行讨论。
|
||||
|
||||
<EFBFBD><EFBFBD>ʼʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ص㣬Ҳ<E3A3AC><D2B2><EFBFBD>Ǵ<EFBFBD><C7B4>ڼ<EFBFBD><DABC>
|
||||
初始时,令第 0 个地方成为待定地点,也就是呆在家里。
|
||||
|
||||
<EFBFBD>ӵ<EFBFBD> 4 <20><><EFBFBD>ص㿪ʼͶƱ<CDB6><C6B1>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD>Ƚϵ<C8BD> 4 <20><><EFBFBD>ط<EFBFBD><D8B7>͵<EFBFBD> 0 <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>˵<EFBFBD> 4 <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>µ<EFBFBD> 4 <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ص㡣
|
||||
从第 4 个地点开始投票,每个人只需要比较第 4 个地方和第 0 个地方的优先级,里,如果超过半数的人选择了第 4 个地方,那么更新第 4 个地方成为待定地点。
|
||||
|
||||
<EFBFBD>Ӻ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD>裬<EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>´<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص㣬ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еط<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD>ͶƱ<EFBFBD><EFBFBD>
|
||||
从后往前不断重复以上步骤,不断更新待定地点,直到所有地方都已经投票。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ص㣬<D8B5><E3A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD> 4 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD>бȽϣ<C8BD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EEBFAA><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ص㣬<D8B5><E3A3AC>ô<EFBFBD>ڶԵ<DAB6> 2 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>ͶƱʱ<C6B1><CAB1>ÿ<EFBFBD><C3BF><EFBFBD>˲<EFBFBD><CBB2><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ǵ<EFBFBD> 2 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> 1 <20><><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD>ҲҪ<D2B2><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͶƱ<CDB6>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD>
|
||||
上面的讨论中,先令第 0 个地点成为待定地点,是因为这样的话第 4 个地点就只需要和这个地点进行比较,而不用考虑其它情况。如果最开始先令第 1 个地点成为待定地点,那么在对第 2 个地点进行投票时,每个人不仅要考虑第 2 个地点与第 1 个地点的优先级,也要考虑与其后投票地点的优先级。
|
||||
|
||||
```java
|
||||
int N = in.nextInt();
|
||||
@ -246,9 +247,9 @@ for (int place = K; place > 0; place--) {
|
||||
System.out.println(ret == 0 ? "otaku" : ret);
|
||||
```
|
||||
|
||||
# 7. <EFBFBD><EFBFBD>-S-expression
|
||||
# 7. 微软-S-expression
|
||||
|
||||
# 8. <EFBFBD><EFBFBD>Ϊ-<2D><><EFBFBD>߷<EFBFBD><DFB7>Ƕ<EFBFBD><C7B6><EFBFBD>
|
||||
# 8. 华为-最高分是多少
|
||||
|
||||
```java
|
||||
int N = in.nextInt();
|
||||
@ -280,7 +281,7 @@ for (int i = 0; i < M; i++) {
|
||||
}
|
||||
```
|
||||
|
||||
# 9. <EFBFBD><EFBFBD>Ϊ-<2D><EFBFBD><F2B5A5B4><EFBFBD><EFBFBD><EFBFBD>¼
|
||||
# 9. 华为-简单错误记录
|
||||
|
||||
```java
|
||||
HashMap<String, Integer> map = new LinkedHashMap<>();
|
||||
@ -300,7 +301,7 @@ for (int i = 0; i < 8 && i < list.size(); i++) {
|
||||
}
|
||||
```
|
||||
|
||||
# 10. <EFBFBD><EFBFBD>Ϊ-<2D>˿<EFBFBD><CBBF>ƴ<EFBFBD>С
|
||||
# 10. 华为-扑克牌大小
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
@ -391,12 +392,12 @@ public class Main {
|
||||
}
|
||||
```
|
||||
|
||||
# 11. ȥ<EFBFBD>Ķ<EFBFBD>-<2D><><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>
|
||||
# 11. 去哪儿-二分查找
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>Ԫ<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>㣺
|
||||
对于有重复元素的有序数组,二分查找需要注意以下要点:
|
||||
|
||||
- if (val <= A[m]) h = m;
|
||||
- <EFBFBD><EFBFBD>Ϊ h <20>ĸ<EFBFBD>ֵΪ m <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> m - 1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD> while ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2>Ϊ l < h<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> m - 1 ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ l <= h<EFBFBD><EFBFBD>
|
||||
- 因为 h 的赋值为 m 而不是 m - 1,因此 while 循环的条件也就为 l < h。(如果是 m - 1 循环条件为 l <= h)
|
||||
|
||||
```java
|
||||
public int getPos(int[] A, int n, int val) {
|
||||
@ -410,7 +411,7 @@ public int getPos(int[] A, int n, int val) {
|
||||
}
|
||||
```
|
||||
|
||||
# 12. ȥ<EFBFBD>Ķ<EFBFBD>-<2D><EFBFBD><D7B8>ظ<EFBFBD><D8B8>ַ<EFBFBD>
|
||||
# 12. 去哪儿-首个重复字符
|
||||
|
||||
```java
|
||||
public char findFirstRepeat(String A, int n) {
|
||||
@ -424,7 +425,7 @@ public char findFirstRepeat(String A, int n) {
|
||||
}
|
||||
```
|
||||
|
||||
# 13. ȥ<EFBFBD>Ķ<EFBFBD>-Ѱ<><D1B0>Coder
|
||||
# 13. 去哪儿-寻找Coder
|
||||
|
||||
```java
|
||||
public String[] findCoder(String[] A, int n) {
|
||||
@ -450,7 +451,7 @@ public String[] findCoder(String[] A, int n) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> javafx.util.Pair<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ʵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> Pair <EFBFBD><EFBFBD>
|
||||
// 牛客网无法导入 javafx.util.Pair,这里就自己实现一下 Pair 类
|
||||
private class Pair<T, K> {
|
||||
T t;
|
||||
K k;
|
||||
@ -470,9 +471,9 @@ private class Pair<T, K> {
|
||||
}
|
||||
```
|
||||
|
||||
# 14. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
# 14. 美团-最大差值
|
||||
|
||||
̰<EFBFBD>IJ<EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
贪心策略。
|
||||
|
||||
```java
|
||||
public int getDis(int[] A, int n) {
|
||||
@ -486,7 +487,7 @@ public int getDis(int[] A, int n) {
|
||||
}
|
||||
```
|
||||
|
||||
# 15. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD>ӷ<EFBFBD>ת
|
||||
# 15. 美团-棋子翻转
|
||||
|
||||
```java
|
||||
public int[][] flipChess(int[][] A, int[][] f) {
|
||||
@ -502,7 +503,7 @@ public int[][] flipChess(int[][] A, int[][] f) {
|
||||
}
|
||||
```
|
||||
|
||||
# 16. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>ݷ<EFBFBD>
|
||||
# 16. 美团-拜访
|
||||
|
||||
```java
|
||||
private Set<String> paths;
|
||||
@ -554,7 +555,7 @@ private void backtracking(int[][] map, int n, int m, int r, int c, int[][] direc
|
||||
}
|
||||
```
|
||||
|
||||
# 17. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-ֱ<><D6B1>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 17. 美团-直方图内最大矩形
|
||||
|
||||
```java
|
||||
public int countArea(int[] A, int n) {
|
||||
@ -570,15 +571,15 @@ public int countArea(int[] A, int n) {
|
||||
}
|
||||
```
|
||||
|
||||
# 18. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 18. 美团-字符串计数
|
||||
|
||||
<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сд<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 26 <EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ıȽϺ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚϲ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD><EFBFBD>бȽϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "ac" <EFBFBD><EFBFBD> "abc"<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ıȽϽ<EFBFBD><EFBFBD><EFBFBD>Ϊ "ac" > "abc"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚϣ<C8BD><CFA3><EFBFBD>Ϊ "abc" <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
字符串都是小写字符,可以把字符串当成是 26 进制。但是字典序的比较和普通的整数比较不同,是从左往右进行比较,例如 "ac" 和 "abc",字典序的比较结果为 "ac" > "abc",如果按照整数方法比较,因为 "abc" 是三位数,显然更大。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD>ȿ<EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD> s1 <20>հײ<D5B0><D7B2>ֺ<EFBFBD> s2 <20><>Ӧ<EFBFBD><D3A6><EFBFBD>ֽ<EFBFBD><D6BD>бȽ<D0B1>ʱ<EFBFBD><CAB1>Ӧ<EFBFBD>ð<EFBFBD> s1 <20>Ŀհײ<D5B0><D7B2>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD> 'a' <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
由于两个字符串的长度可能不想等,在 s1 空白部分和 s2 对应部分进行比较时,应该把 s1 的空白部分看成是 'a' 字符进行填充的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Ҫע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>s1 <EFBFBD><EFBFBD> s2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ len<sub>i</sub> <EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>Ƚ<EFBFBD>ǰ<EFBFBD><EFBFBD> i <20><><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'aaa' <EFBFBD><EFBFBD> 'bbb' <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 2 <20>ĸ<EFBFBD><C4B8><EFBFBD>Ϊ 'aa' <EFBFBD><EFBFBD> 'bb' <EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD>沿<EFBFBD>ֵ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
还有一点要注意的是,s1 到 s2 长度为 len<sub>i</sub> 的字符串个数只比较前面 i 个字符。例如 'aaa' 和 'bbb' ,长度为 2 的个数为 'aa' 到 'bb' 的字符串个数,不需要考虑后面部分的字符。
|
||||
|
||||
<EFBFBD><EFBFBD>ͳ<EFBFBD>Ƹ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> len1 <20><>ʼһֱ<D2BB><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>ȣ<EFBFBD>ÿ<EFBFBD><C3BF>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>ͳ<EFBFBD>Ƴ<EFBFBD><C6B3><EFBFBD>Ϊ i <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在统计个数时,从 len1 开始一直遍历到最大合法长度,每次循环都统计长度为 i 的子字符串个数。
|
||||
|
||||
```java
|
||||
String s1 = in.next();
|
||||
@ -601,7 +602,7 @@ for (int i = len1; i <= len; i++) {
|
||||
System.out.println(ret - 1);
|
||||
```
|
||||
|
||||
# 19. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-ƽ<><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 19. 美团-平均年龄
|
||||
|
||||
```java
|
||||
int W = in.nextInt();
|
||||
@ -609,15 +610,15 @@ double Y = in.nextDouble();
|
||||
double x = in.nextDouble();
|
||||
int N = in.nextInt();
|
||||
while (N-- > 0) {
|
||||
Y++; // <EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䶼Ҫ<EFBFBD><EFBFBD> 1
|
||||
Y++; // 老员工每年年龄都要加 1
|
||||
Y += (21 - Y) * x;
|
||||
}
|
||||
System.out.println((int) Math.ceil(Y));
|
||||
```
|
||||
|
||||
# 20. <EFBFBD>ٶ<EFBFBD>-<2D>ﷸת<EFB7B8><D7AA>
|
||||
# 20. 百度-罪犯转移
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ֺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD>ֺͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
部分和问题,将每次求的部分和缓存起来。
|
||||
|
||||
```java
|
||||
int n = in.nextInt();
|
||||
@ -640,7 +641,7 @@ for (int s = 0, e = c - 1; e < n; s++, e++) {
|
||||
System.out.println(cnt);
|
||||
```
|
||||
|
||||
# 22. <EFBFBD>ٶ<EFBFBD>-<2D>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>ֽ
|
||||
# 22. 百度-裁减网格纸
|
||||
|
||||
```java
|
||||
int n = in.nextInt();
|
||||
@ -658,11 +659,11 @@ for (int i = 0; i < n; i++) {
|
||||
System.out.println((int) Math.pow(Math.max(maxX - minX, maxY - minY), 2));
|
||||
```
|
||||
|
||||
# 23. <EFBFBD>ٶ<EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 23. 百度-钓鱼比赛
|
||||
|
||||
P ( <EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ) = 1 - P ( һ<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> )
|
||||
P ( 至少钓一条鱼 ) = 1 - P ( 一条也钓不到 )
|
||||
|
||||
<EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫһ<EFBFBD><EFBFBD>һ<EFBFBD>н<EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> in.nextDouble()<EFBFBD><EFBFBD>
|
||||
坑:读取概率矩阵的时候,需要一行一行进行读取,而不能直接用 in.nextDouble()。
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
@ -673,11 +674,11 @@ public static void main(String[] args) {
|
||||
int x = in.nextInt();
|
||||
int y = in.nextInt();
|
||||
int t = in.nextInt();
|
||||
in.nextLine(); // <EFBFBD><EFBFBD>
|
||||
in.nextLine(); // 坑
|
||||
double pcc = 0.0;
|
||||
double sum = 0.0;
|
||||
for (int i = 1; i <= n; i++) {
|
||||
String[] token = in.nextLine().split(" "); // <EFBFBD><EFBFBD>
|
||||
String[] token = in.nextLine().split(" "); // 坑
|
||||
for (int j = 1; j <= m; j++) {
|
||||
double p = Double.parseDouble(token[j - 1]);
|
||||
// double p = in.nextDouble();
|
||||
@ -701,13 +702,13 @@ private static double computePOfIRT(double p, int t) {
|
||||
}
|
||||
```
|
||||
|
||||
# 24. <EFBFBD>ٶ<EFBFBD>-Ģ<><C4A2><EFBFBD><EFBFBD>
|
||||
# 24. 百度-蘑菇阵
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>ݻᳬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> DP<EFBFBD><EFBFBD>
|
||||
这题用回溯会超时,需要用 DP。
|
||||
|
||||
dp[i][j] <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (i,j) λ<>ò<EFBFBD><C3B2>ᴥ<EFBFBD><E1B4A5>Ģ<EFBFBD><C4A2><EFBFBD>ĸ<EFBFBD><C4B8>ʡ<EFBFBD><CAA1><EFBFBD><EFBFBD><EFBFBD> N\*M <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> i == N || j == M<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô (i,j) ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
dp[i][j] 表示到达 (i,j) 位置不会触碰蘑菇的概率。对于 N\*M 矩阵,如果 i == N || j == M,那么 (i,j) 只能有一个移动方向;其它情况下能有两个移动方向。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> 3 <20>к͵<D0BA> 3 <20><>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD>
|
||||
考虑以下矩阵,其中第 3 行和第 3 列只能往一个方向移动,而其它位置可以有两个方向移动。
|
||||
|
||||
|
||||
```java
|
||||
|
477
notes/HTTP.md
477
notes/HTTP.md
@ -1,84 +1,85 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [Web <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#web-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [基础概念](#基础概念)
|
||||
* [Web 基础](#web-基础)
|
||||
* [URL](#url)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>)
|
||||
* [HTTP <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#http-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [GET<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Դ](#get<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Դ)
|
||||
* [POST<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#post<73><74><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [HEAD<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD>](#head<61><64>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD>)
|
||||
* [PUT<EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD>ļ<EFBFBD>](#put<EFBFBD>ϴ<EFBFBD><EFBFBD>ļ<EFBFBD>)
|
||||
* [DELETE<EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>](#deleteɾ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>)
|
||||
* [OPTIONS<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ֧<EFBFBD>ֵķ<EFBFBD><EFBFBD><EFBFBD>](#options<EFBFBD><EFBFBD>ѯ֧<EFBFBD>ֵķ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [TRACE<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>](#trace<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>)
|
||||
* [CONNECT<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD><EFBFBD><EFBFBD>](#connectҪ<74><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD>)
|
||||
* [HTTP ״̬<EFBFBD><EFBFBD>](#http-״̬<EFBFBD><EFBFBD>)
|
||||
* [2XX <EFBFBD>ɹ<EFBFBD>](#2xx-<EFBFBD>ɹ<EFBFBD>)
|
||||
* [3XX <EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>](#3xx-<EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4XX <EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD>](#4xx-<EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [5XX <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#5xx-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [HTTP <EFBFBD>ײ<EFBFBD>](#http-<EFBFBD>ײ<EFBFBD>)
|
||||
* [ͨ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>](#ͨ<><CDA8><EFBFBD>ײ<EFBFBD><D7B2>ֶ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2>ֶ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>Ӧ<EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>](#<23><>Ӧ<EFBFBD>ײ<EFBFBD><D7B2>ֶ<EFBFBD>)
|
||||
* [ʵ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>](#ʵ<><CAB5><EFBFBD>ײ<EFBFBD><D7B2>ֶ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>)
|
||||
* [请求和响应报文](#请求和响应报文)
|
||||
* [HTTP 方法](#http-方法)
|
||||
* [GET:获取资源](#get获取资源)
|
||||
* [POST:传输实体主体](#post传输实体主体)
|
||||
* [HEAD:获取报文首部](#head获取报文首部)
|
||||
* [PUT:上传文件](#put上传文件)
|
||||
* [DELETE:删除文件](#delete删除文件)
|
||||
* [OPTIONS:查询支持的方法](#options查询支持的方法)
|
||||
* [TRACE:追踪路径](#trace追踪路径)
|
||||
* [CONNECT:要求用隧道协议连接代理](#connect要求用隧道协议连接代理)
|
||||
* [HTTP 状态码](#http-状态码)
|
||||
* [2XX 成功](#2xx-成功)
|
||||
* [3XX 重定向](#3xx-重定向)
|
||||
* [4XX 客户端错误](#4xx-客户端错误)
|
||||
* [5XX 服务器错误](#5xx-服务器错误)
|
||||
* [HTTP 首部](#http-首部)
|
||||
* [通用首部字段](#通用首部字段)
|
||||
* [请求首部字段](#请求首部字段)
|
||||
* [响应首部字段](#响应首部字段)
|
||||
* [实体首部字段](#实体首部字段)
|
||||
* [具体应用](#具体应用)
|
||||
* [Cookie](#cookie)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>ֿ鴫<EFBFBD><EFBFBD>](#<23>ֿ鴫<D6BF><E9B4AB>)
|
||||
* [<EFBFBD>ಿ<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD>](#<23>ಿ<EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>](#ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>)
|
||||
* [缓存](#缓存)
|
||||
* [持久连接](#持久连接)
|
||||
* [编码](#编码)
|
||||
* [分块传输](#分块传输)
|
||||
* [多部分对象集合](#多部分对象集合)
|
||||
* [范围请求](#范围请求)
|
||||
* [内容协商](#内容协商)
|
||||
* [虚拟主机](#虚拟主机)
|
||||
* [通信数据转发](#通信数据转发)
|
||||
* [HTTPs](#https)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>֤](#<EFBFBD><EFBFBD>֤)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [HTTP/1.0 <EFBFBD><EFBFBD> HTTP/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#http10-<EFBFBD><EFBFBD>-http11-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [加密](#加密)
|
||||
* [认证](#认证)
|
||||
* [完整性](#完整性)
|
||||
* [HTTP/1.0 与 HTTP/1.1 的区别](#http10-与-http11-的区别)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
## Web <20><><EFBFBD><EFBFBD>
|
||||
# 基础概念
|
||||
|
||||
- HTTP<54><50>HyperText Transfer Protocol<6F><6C><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>飩<EFBFBD><E9A3A9>
|
||||
- WWW<57><57>Word Wide Web<65><62><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD><EFBFBD><EFBFBD>HTML<4D><4C>HTTP<54><50>URL<52><4C>
|
||||
- RFC<EFBFBD><EFBFBD>Request for Comments<74><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飩<EFBFBD><E9A3A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>
|
||||
## Web 基础
|
||||
|
||||
- HTTP(HyperText Transfer Protocol,超为本传输协议)。
|
||||
- WWW(Word Wide Web)的三种技术:HTML、HTTP、URL。
|
||||
- RFC(Request for Comments,征求修正意见书),互联网的设计文档。
|
||||
|
||||
## URL
|
||||
|
||||
- URI<EFBFBD><EFBFBD>Uniform Resource Indentifier<EFBFBD><EFBFBD>ͳһ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- URL<EFBFBD><EFBFBD>Uniform Resource Locator<EFBFBD><EFBFBD>ͳһ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- URN<EFBFBD><EFBFBD>Uniform Resource Name<EFBFBD><EFBFBD>ͳһ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> urn:isbn:0-486-27557-4 <EFBFBD><EFBFBD>
|
||||
- URI(Uniform Resource Indentifier,统一资源标识符)
|
||||
- URL(Uniform Resource Locator,统一资源定位符)
|
||||
- URN(Uniform Resource Name,统一资源名称),例如 urn:isbn:0-486-27557-4 。
|
||||
|
||||
URI <EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL <EFBFBD><EFBFBD> URN<EFBFBD><EFBFBD>Ŀǰ WEB ֻ<EFBFBD><EFBFBD> URL <EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL<EFBFBD><EFBFBD>
|
||||
URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基本都是 URL。
|
||||
|
||||

|
||||

|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 请求和响应报文
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**请求报文**
|
||||
|
||||

|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**响应报文**
|
||||
|
||||

|
||||

|
||||
|
||||
# HTTP <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# HTTP 方法
|
||||
|
||||
<EFBFBD>ͻ<EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>һ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΡ<EFBFBD>
|
||||
客户端发送的请求报文第一行为请求行,包含了方法字段。
|
||||
|
||||
## GET<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Դ
|
||||
## GET:获取资源
|
||||
|
||||
## POST<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## POST:传输实体主体
|
||||
|
||||
POST <EFBFBD><EFBFBD>ҪĿ<EFBFBD>IJ<EFBFBD><EFBFBD>ǻ<EFBFBD>ȡ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
POST 主要目的不是获取资源,而是传输实体主体数据。
|
||||
|
||||
GET <EFBFBD><EFBFBD> POST <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GET <20>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>ѯ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL<52>У<EFBFBD><D0A3><EFBFBD> POST <20>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD>岿<EFBFBD>֡<EFBFBD>
|
||||
GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL中,而 POST 的参数存储在实体主体部分。
|
||||
|
||||
```
|
||||
GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1
|
||||
@ -89,318 +90,318 @@ Host: w3schools.com
|
||||
name1=value1&name2=value2
|
||||
```
|
||||
|
||||
GET <EFBFBD>Ĵ<EFBFBD><EFBFBD>η<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> POST <20><>ȫ<EFBFBD>Խϲ<CFB2><EEA3AC>Ϊ GET <20><><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD> URL <20>ǿɼ<C7BF><C9BC>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ܻ<EFBFBD>й¶˽<C2B6><CBBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GET ֻ֧<EFBFBD><EFBFBD> ASCII <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD> POST ֧<>ֱ<EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
GET 的传参方式相比于 POST 安全性较差,因为 GET 传的参数在 URL 是可见的,可能会泄露私密信息。并且 GET 只支持 ASCII 字符,如果参数为中文则可能会出现乱码,而 POST 支持标准字符集。
|
||||
|
||||
## HEAD<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD>
|
||||
## HEAD:获取报文首部
|
||||
|
||||
<EFBFBD><EFBFBD> GET <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>岿<EFBFBD>֡<EFBFBD>
|
||||
和 GET 方法一样,但是不返回报文实体主体部分。
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD> URL <20><><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ȡ<EFBFBD>
|
||||
主要用于确认 URL 的有效性以及资源更新的日期时间等。
|
||||
|
||||
## PUT<EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
## PUT:上传文件
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD>κ<EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD>ڰ<EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬һ<EFBFBD><EFBFBD> WEB <20><>վ<EFBFBD><D5BE>ʹ<EFBFBD>ø÷<C3B8><C3B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般 WEB 网站不使用该方法。
|
||||
|
||||
## DELETE<EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||
## DELETE:删除文件
|
||||
|
||||
<EFBFBD><EFBFBD> PUT <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>෴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||||
与 PUT 功能相反,并且同样不带验证机制。
|
||||
|
||||
## OPTIONS<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ֧<EFBFBD>ֵķ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## OPTIONS:查询支持的方法
|
||||
|
||||
<EFBFBD><EFBFBD>ѯָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL <20>ܹ<EFBFBD>֧<EFBFBD>ֵķ<D6B5><C4B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
查询指定的 URL 能够支持的方法。
|
||||
|
||||
<EFBFBD>᷵<EFBFBD><EFBFBD> Allow: GET, POST, HEAD, OPTIONS <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
会返回 Allow: GET, POST, HEAD, OPTIONS 这样的内容。
|
||||
|
||||
## TRACE<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>
|
||||
## TRACE:追踪路径
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ὣͨ<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>ˡ<EFBFBD>
|
||||
服务器会将通信路径返回给客户端。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Max-Forwards <EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪ 0 ʱ<><CAB1>ֹͣ<CDA3><D6B9><EFBFBD>䡣
|
||||
发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。
|
||||
|
||||
TRACE һ<EFBFBD>㲻<EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD> XST <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Cross-Site Tracing<6E><67><EFBFBD><EFBFBD>վ<D5BE>٣<EFBFBD><D9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><CBB8><EFBFBD><EFBFBD><EFBFBD>ȥʹ<C8A5><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
TRACE 一般不会使用,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪),因此更不会去使用它。
|
||||
|
||||

|
||||

|
||||
|
||||
## CONNECT<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## CONNECT:要求用隧道协议连接代理
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD> SSL<EFBFBD><EFBFBD>Secure Sokets Layer<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD> TLS<EFBFBD><EFBFBD>Transport Layer Security<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㰲ȫ<EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD><EFBFBD>ܺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䡣
|
||||
主要使用 SSL(Secure Sokets Layer,安全套接字)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。
|
||||
|
||||

|
||||

|
||||
|
||||
# HTTP ״̬<EFBFBD><EFBFBD>
|
||||
# HTTP 状态码
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>һ<EFBFBD><EFBFBD>Ϊ״̬<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
服务器返回的响应报文中第一行为状态行,包含了状态码以及原因短语,来告知客户端请求的结果。
|
||||
|
||||
| ״̬<EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> | ԭ<><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| 状态码 | 类别 | 原因短语 |
|
||||
| --- | --- | --- |
|
||||
| 1XX | Informational<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>״̬<EFBFBD>룩 | <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> |
|
||||
| 2XX | Success<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>״̬<EFBFBD>룩 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| 3XX | Redirection<EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>룩 | <20><>Ҫ<EFBFBD><D2AA><EFBFBD>и<EFBFBD><D0B8>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| 4XX | Client Error<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>룩 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| 5XX | Server Error<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>룩 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| 1XX | Informational(信息性状态码) | 接收的请求正在处理 |
|
||||
| 2XX | Success(成功状态码) | 请求正常处理完毕 |
|
||||
| 3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
|
||||
| 4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
|
||||
| 5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
|
||||
|
||||
## 2XX <EFBFBD>ɹ<EFBFBD>
|
||||
## 2XX 成功
|
||||
|
||||
- **200 OK**
|
||||
|
||||
- **204 No Content**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>岿<EFBFBD>֡<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD>ӿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʹ<EFBFBD>á<EFBFBD>
|
||||
- **204 No Content**:请求已经成功处理,但是返回的响应报文不包含实体的主体部分。一般在只需要从客户端往服务器发送信息,而不需要返回数据时使用。
|
||||
|
||||
- **206 Partial Content**
|
||||
|
||||
## 3XX <EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3XX 重定向
|
||||
|
||||
- **301 Moved Permanently**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>
|
||||
- **301 Moved Permanently**:永久性重定向
|
||||
|
||||
- **302 Found**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>
|
||||
- **302 Found**:临时性重定向
|
||||
|
||||
- **303 See Other**
|
||||
|
||||
- ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ HTTP Э<EFBFBD><EFBFBD><EFBFBD>涨 301<EFBFBD><EFBFBD>302 ״̬<EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> POST <20><><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD> GET <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><C7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 301<EFBFBD><EFBFBD>302 <EFBFBD><EFBFBD> 303 ״̬<EFBFBD>µ<EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> POST <20><><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD> GET <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 注:虽然 HTTP 协议规定 301、302 状态下重定向时不允许把 POST 方法改成 GET 方法,但是大多数浏览器都会 在 301、302 和 303 状态下的重定向把 POST 方法改成 GET 方法。
|
||||
|
||||
- **304 Not Modified**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>磺If-Match<EFBFBD><EFBFBD>If-ModifiedSince<EFBFBD><EFBFBD>If-None-Match<EFBFBD><EFBFBD>If-Range<EFBFBD><EFBFBD>If-Unmodified-Since<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>᷵<EFBFBD><EFBFBD> 304 ״̬<EFBFBD>롣
|
||||
- **304 Not Modified**:如果请求报文首部包含一些条件,例如:If-Match,If-ModifiedSince,If-None-Match,If-Range,If-Unmodified-Since,但是不满足条件,则服务器会返回 304 状态码。
|
||||
|
||||
- **307 Temporary Redirect**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 302 <20>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD> 307 Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> POST <20><><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD> GET <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- **307 Temporary Redirect**:临时重定向,与 302 的含义类似,但是 307 要求浏览器不会把重定向请求的 POST 方法改成 GET 方法。
|
||||
|
||||
## 4XX <EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4XX 客户端错误
|
||||
|
||||
- **400 Bad Request**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- **400 Bad Request**:请求报文中存在语法错误
|
||||
|
||||
- **401 Unauthorized**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> HTTP <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>BASIC <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>DIGEST <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD>ѽ<EFBFBD><EFBFBD>й<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>֤ʧ<EFBFBD>ܡ<EFBFBD>
|
||||
- **401 Unauthorized**:该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。如果之前已进行过一次请求,则表示用户认证失败。
|
||||
|
||||

|
||||

|
||||
|
||||
- **403 Forbidden**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>б<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>
|
||||
- **403 Forbidden**:请求被拒绝,服务器端没有必要给出拒绝的详细理由。
|
||||
|
||||
- **404 Not Found**
|
||||
|
||||
## 5XX <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 5XX 服务器错误
|
||||
|
||||
- **500 Internal Server Error**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- **500 Internal Server Error**:服务器正在执行请求时发生错误
|
||||
|
||||
- **503 Service Unavilable**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- **503 Service Unavilable**:该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
|
||||
|
||||
# HTTP <EFBFBD>ײ<EFBFBD>
|
||||
# HTTP 首部
|
||||
|
||||
<EFBFBD><EFBFBD> 4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶΣ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶΡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶΡ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ײ<EFBFBD><EFBFBD>ֶκ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶΡ<EFBFBD>
|
||||
有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶμ<EFBFBD><EFBFBD>京<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫȫ<EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>
|
||||
各种首部字段及其含义如下(不需要全记,仅供查阅):
|
||||
|
||||
## ͨ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
## 通用首部字段
|
||||
|
||||
| <EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 首部字段名 | 说明 |
|
||||
| -- | -- |
|
||||
| Cache-Control | <EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ |
|
||||
| Connection | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ӵĹ<D3B5><C4B9><EFBFBD> |
|
||||
| Date | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> |
|
||||
| Pragma | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> |
|
||||
| Trailer | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĩ<EFBFBD>˵<EFBFBD><EFBFBD>ײ<EFBFBD>һ<EFBFBD><EFBFBD> |
|
||||
| Transfer-Encoding | ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뷽ʽ |
|
||||
| Upgrade | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD> |
|
||||
| Via | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ |
|
||||
| Warning | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ |
|
||||
| Cache-Control | 控制缓存的行为 |
|
||||
| Connection | 逐跳首部、 连接的管理 |
|
||||
| Date | 创建报文的日期时间 |
|
||||
| Pragma | 报文指令 |
|
||||
| Trailer | 报文末端的首部一览 |
|
||||
| Transfer-Encoding | 指定报文主体的传输编码方式 |
|
||||
| Upgrade | 升级为其他协议 |
|
||||
| Via | 代理服务器的相关信息 |
|
||||
| Warning | 错误通知 |
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
## 请求首部字段
|
||||
|
||||
| <EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 首部字段名 | 说明 |
|
||||
| -- | -- |
|
||||
| Accept | <EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Accept-Charset | <EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Accept-Encoding | <EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Accept-Language | <EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD> |
|
||||
| Authorization | Web<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Ϣ |
|
||||
| Expect | <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD>Ϊ |
|
||||
| From | <EFBFBD>û<EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ |
|
||||
| Host | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| If-Match | <EFBFBD>Ƚ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>ETag<EFBFBD><EFBFBD> |
|
||||
| If-Modified-Since | <EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> |
|
||||
| If-None-Match | <EFBFBD>Ƚ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD> If-Match <EFBFBD>෴<EFBFBD><EFBFBD> |
|
||||
| If-Range | <EFBFBD><EFBFBD>Դδ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD> Byte <20>ķ<EFBFBD>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD> |
|
||||
| If-Unmodified-Since | <EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䣨<EFBFBD><EFBFBD>If-Modified-Since<EFBFBD>෴<EFBFBD><EFBFBD> |
|
||||
| Max-Forwards | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Proxy-Authorization | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Ϣ |
|
||||
| Range | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڷ<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Referer | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URI <20><>ԭʼ<D4AD><CABC>ȡ<EFBFBD><C8A1> |
|
||||
| TE | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD> |
|
||||
| User-Agent | HTTP <EFBFBD>ͻ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ |
|
||||
| Accept | 用户代理可处理的媒体类型 |
|
||||
| Accept-Charset | 优先的字符集 |
|
||||
| Accept-Encoding | 优先的内容编码 |
|
||||
| Accept-Language | 优先的语言(自然语言) |
|
||||
| Authorization | Web认证信息 |
|
||||
| Expect | 期待服务器的特定行为 |
|
||||
| From | 用户的电子邮箱地址 |
|
||||
| Host | 请求资源所在服务器 |
|
||||
| If-Match | 比较实体标记(ETag) |
|
||||
| If-Modified-Since | 比较资源的更新时间 |
|
||||
| If-None-Match | 比较实体标记(与 If-Match 相反) |
|
||||
| If-Range | 资源未更新时发送实体 Byte 的范围请求 |
|
||||
| If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
|
||||
| Max-Forwards | 最大传输逐跳数 |
|
||||
| Proxy-Authorization | 代理服务器要求客户端的认证信息 |
|
||||
| Range | 实体的字节范围请求 |
|
||||
| Referer | 对请求中 URI 的原始获取方 |
|
||||
| TE | 传输编码的优先级 |
|
||||
| User-Agent | HTTP 客户端程序的信息 |
|
||||
|
||||
## <EFBFBD><EFBFBD>Ӧ<EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
## 响应首部字段
|
||||
|
||||
| <EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 首部字段名 | 说明 |
|
||||
| -- | -- |
|
||||
| Accept-Ranges | <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڷ<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Age | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> |
|
||||
| ETag | <EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ |
|
||||
| Location | <EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>URI |
|
||||
| Proxy-Authenticate | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կͻ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Ϣ |
|
||||
| Retry-After | <EFBFBD><EFBFBD><EFBFBD>ٴη<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> |
|
||||
| Server | HTTP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD>װ<EFBFBD><EFBFBD>Ϣ |
|
||||
| Vary | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ |
|
||||
| WWW-Authenticate | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կͻ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Ϣ |
|
||||
| Accept-Ranges | 是否接受字节范围请求 |
|
||||
| Age | 推算资源创建经过时间 |
|
||||
| ETag | 资源的匹配信息 |
|
||||
| Location | 令客户端重定向至指定URI |
|
||||
| Proxy-Authenticate | 代理服务器对客户端的认证信息 |
|
||||
| Retry-After | 对再次发起请求的时机要求 |
|
||||
| Server | HTTP服务器的安装信息 |
|
||||
| Vary | 代理服务器缓存的管理信息 |
|
||||
| WWW-Authenticate | 服务器对客户端的认证信息 |
|
||||
|
||||
## ʵ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
## 实体首部字段
|
||||
|
||||
| <EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 首部字段名 | 说明 |
|
||||
| -- | -- |
|
||||
| Allow | <EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>HTTP<EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Content-Encoding | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õı<EFBFBD><EFBFBD>뷽ʽ |
|
||||
| Content-Language | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Content-Length | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD> <20>ֽڣ<D6BD> |
|
||||
| Content-Location | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>URI |
|
||||
| Content-MD5 | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD>ժҪ |
|
||||
| Content-Range | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>÷<EFBFBD>Χ |
|
||||
| Content-Type | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Expires | ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> |
|
||||
| Last-Modified | <EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> |
|
||||
| Allow | 资源可支持的HTTP方法 |
|
||||
| Content-Encoding | 实体主体适用的编码方式 |
|
||||
| Content-Language | 实体主体的自然语言 |
|
||||
| Content-Length | 实体主体的大小(单位: 字节) |
|
||||
| Content-Location | 替代对应资源的URI |
|
||||
| Content-MD5 | 实体主体的报文摘要 |
|
||||
| Content-Range | 实体主体的位置范围 |
|
||||
| Content-Type | 实体主体的媒体类型 |
|
||||
| Expires | 实体主体过期的日期时间 |
|
||||
| Last-Modified | 资源的最后修改日期时间 |
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>
|
||||
# 具体应用
|
||||
|
||||
## Cookie
|
||||
|
||||
HTTP Э<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP Э<>龡<EFBFBD><E9BEA1><EFBFBD>ܼ<DCBC>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>HTTP/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>
|
||||
HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD><EFBFBD><EFBFBD> Set-Cookie <20>ֶΣ<D6B6><CEA3>ͻ<EFBFBD><CDBB>˵õ<CBB5><C3B5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD> Cookie <20><><EFBFBD>ݱ<EFBFBD><DDB1>浽<EFBFBD><E6B5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>´<EFBFBD><C2B4>ٷ<EFBFBD><D9B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD> Cookie ֵ<><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD> Cookie <20>ֶΣ<D6B6><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><D6AA><EFBFBD>ͻ<EFBFBD><CDBB>˵<EFBFBD>״̬<D7B4><CCAC>Ϣ<EFBFBD>ˡ<EFBFBD>Cookie ״̬<D7B4><CCAC>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>ڿͻ<DABF><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
服务器发送的响应报文包含 Set-Cookie 字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。下次再发送请求时,从浏览器中读出 Cookie 值,在请求报文中包含 Cookie 字段,这样服务器就知道客户端的状态信息了。Cookie 状态信息保存在客户端浏览器中,而不是服务器上。
|
||||
|
||||

|
||||

|
||||
|
||||
Set-Cookie <EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>
|
||||
Set-Cookie 字段有以下属性:
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 属性 | 说明 |
|
||||
| -- | -- |
|
||||
| NAME=VALUE | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƺ<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| expires=DATE | Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD>ǰΪֹ<EFBFBD><EFBFBD> |
|
||||
| path=PATH | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>ļ<EFBFBD>Ŀ¼<EFBFBD><EFBFBD>Ϊ Cookie <20><><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>Ϊ<EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>ļ<EFBFBD>Ŀ¼<C4BF><C2BC> |
|
||||
| domain=<EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><>Ϊ Cookie <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD> Cookie <20>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| Secure | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTPS <EFBFBD><EFBFBD>ȫͨ<EFBFBD><EFBFBD>ʱ<EFBFBD>Żᷢ<EFBFBD><EFBFBD> Cookie |
|
||||
| HttpOnly | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>ʹ Cookie <EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD> JavaScript <EFBFBD>ű<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| NAME=VALUE | 赋予 Cookie 的名称和其值(必需项) |
|
||||
| expires=DATE | Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止) |
|
||||
| path=PATH | 将服务器上的文件目录作为 Cookie 的适用对象(若不指定则默认为文档所在的文件目录) |
|
||||
| domain=域名 | 作为 Cookie 适用对象的域名(若不指定则默认为创建 Cookie 的服务器的域名) |
|
||||
| Secure | 仅在 HTTPS 安全通信时才会发送 Cookie |
|
||||
| HttpOnly | 加以限制,使 Cookie 不能被 JavaScript 脚本访问 |
|
||||
|
||||
**Session <EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**Session 和 Cookie 区别**
|
||||
|
||||
Session <EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֶΣ<EFBFBD>ÿ<EFBFBD><EFBFBD> Session <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Ψһ<CEA8><D2BB>ʶ<EFBFBD><CAB6>Session ID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Session ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB>˷<EFBFBD><CBB7>͵<EFBFBD><CDB5><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ľͰ<C4BE><CDB0><EFBFBD><EFBFBD><EFBFBD> Set-Cookie <20>ֶΣ<D6B6><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ϊ sid <20>ļ<EFBFBD>ֵ<EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>Ծ<EFBFBD><D4BE><EFBFBD> Session ID<49><44><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD>Ͱ<EFBFBD> Cookie <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD> Session ID<EFBFBD><EFBFBD>HTTP <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> Session <EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>״̬<EFBFBD>ģ<EFBFBD>Session <20><><EFBFBD>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>Cookie <20><><EFBFBD>ڿͻ<DABF><CDBB>ˡ<EFBFBD>
|
||||
Session 是服务器用来跟踪用户的一种手段,每个 Session 都有一个唯一标识:Session ID。当服务器创建了一个 Session 时,给客户端发送的响应报文就包含了 Set-Cookie 字段,其中有一个名为 sid 的键值对,这个键值对就是 Session ID。客户端收到后就把 Cookie 保存在浏览器中,并且之后发送的请求报文都包含 Session ID。HTTP 就是通过 Session 和 Cookie 这两种方式一起合作来实现跟踪用户状态的,Session 用于服务器端,Cookie 用于客户端。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**浏览器禁用 Cookie 的情况**
|
||||
|
||||
<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> URL <20><>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sid=xxx <EFBFBD><EFBFBD>
|
||||
会使用 URL 重写技术,在 URL 后面加上 sid=xxx 。
|
||||
|
||||
**ʹ<EFBFBD><EFBFBD> Cookie ʵ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>д**
|
||||
**使用 Cookie 实现用户名和密码的自动填写**
|
||||
|
||||
<EFBFBD><EFBFBD>վ<EFBFBD>ű<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD> Cookie <20>ж<EFBFBD>ȡ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD>Ӷ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>д<EFBFBD><D0B4>
|
||||
网站脚本会自动从 Cookie 中读取用户名和密码,从而实现自动填写。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 缓存
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>淽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>档
|
||||
有两种缓存方法:让代理服务器进行缓存和让客户端浏览器进行缓存。
|
||||
|
||||
Cache-Control <EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
|
||||
Cache-Control 用于控制缓存的行为。
|
||||
|
||||
Cache-Control: no-cache <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֺ<EFBFBD><EFBFBD>壬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD><EFBFBD>и<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ͻ<EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD><EFBFBD>и<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>档
|
||||
Cache-Control: no-cache 有两种含义,如果是客户端向缓存服务器发送的请求报文中含有该指令,表示客户端不想要缓存的资源;如果是源服务器向缓存服务器发送的响应报文中含有该指令,表示缓存服务器不能对资源进行缓存。
|
||||
|
||||
Expires <EFBFBD>ֶο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դʲôʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD> Cache-Control <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> max-age ָ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶ<EFBFBD> Expires<65><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD> max-age ָ<EFBFBD>
|
||||
Expires 字段可以用于告知缓存服务器该资源什么时候会过期。当首部字段 Cache-Control 有指定 max-age 指令时,比起首部字段 Expires,会优先处理 max-age 指令。
|
||||
|
||||
## <EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 持久连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼƬ<EFBFBD><EFBFBD> HTML ҳ<><D2B3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTML ҳ<><D2B3><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼƬ<CDBC><C6AC>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> HTTP ͨ<>ž<EFBFBD>Ҫ<EFBFBD>Ͽ<EFBFBD>һ<EFBFBD><D2BB> TCP <20><><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD>ͶϿ<CDB6><CFBF>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><DCB4><EFBFBD>**<2A>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD>** ֻ<><D6BB>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> TCP <20><><EFBFBD>Ӿ<EFBFBD><D3BE>ܽ<EFBFBD><DCBD>ж<EFBFBD><D0B6><EFBFBD> HTTP ͨ<EFBFBD>š<EFBFBD>HTTP/1.1 <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>϶<EFBFBD><EFBFBD>dz־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源,如果每进行一次 HTTP 通信就要断开一次 TCP 连接,连接建立和断开的开销会很大。**持久连接** 只需要进行一次 TCP 连接就能进行多次 HTTP 通信。HTTP/1.1 开始,所有的连接默认都是持久连接。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD> Connection <20>ײ<EFBFBD><D7B2>ֶν<D6B6><CEBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD>HTTP/1.1 <EFBFBD><EFBFBD>ʼ HTTP Ĭ<EFBFBD><EFBFBD><EFBFBD>dz־û<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ͽ<EFBFBD> TCP <20><><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>Ҫ<EFBFBD>ɿͻ<C9BF><CDBB>˻<EFBFBD><CBBB>߷<EFBFBD><DFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD>ʹ<EFBFBD><CAB9> Connection: close<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP/1.1 ֮ǰĬ<EFBFBD><EFBFBD><EFBFBD>Ƿdz־û<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫά<EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD> Keep-Alive<EFBFBD><EFBFBD>
|
||||
持久连接需要使用 Connection 首部字段进行管理。HTTP/1.1 开始 HTTP 默认是持久化连接的,如果要断开 TCP 连接,需要由客户端或者服务器端提出断开,使用 Connection: close;而在 HTTP/1.1 之前默认是非持久化连接的,如果要维持持续连接,需要使用 Keep-Alive。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>Ӧ֮<EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
管线化方式可以同时发送多个请求和响应,而不需要发送一个请求然后等待响应之后再发下一个请求。
|
||||
|
||||

|
||||

|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 编码
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>루Encoding<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϊ<EFBFBD>˶<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õı<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>gzip<EFBFBD><EFBFBD>compress<EFBFBD><EFBFBD>deflate<EFBFBD><EFBFBD>identity<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> identity <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
编码(Encoding)主要是为了对实体进行压缩。常用的编码有:gzip、compress、deflate、identity,其中 identity 表示不执行压缩的编码格式。
|
||||
|
||||
## <EFBFBD>ֿ鴫<EFBFBD><EFBFBD>
|
||||
## 分块传输
|
||||
|
||||
<EFBFBD>ֿ鴫<EFBFBD>䣨Chunked Transfer Coding<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷָ<EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾҳ<EFBFBD>档
|
||||
分块传输(Chunked Transfer Coding)可以把数据分割成多块,让浏览器逐步显示页面。
|
||||
|
||||
## <EFBFBD>ಿ<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 多部分对象集合
|
||||
|
||||
һ<EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿɺ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>ʵ<EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD> boundary <20>ֶζ<D6B6><CEB6><EFBFBD><EFBFBD>ķָ<C4B7><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>зָ<D0B7><D6B8><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2>ֶΡ<D6B6>
|
||||
一份报文主体内可含有多类型的实体同时发送,每个部分之间用 boundary 字段定义的分隔符进行分隔;每个部分都可以有首部字段。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>磬<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
例如,上传多个表单时可以使用如下方式:
|
||||
|
||||

|
||||

|
||||
|
||||
## <EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 范围请求
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ÿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
如果网络出现中断,服务器只发送了一部分数据,范围请求使得客户端能够只请求未发送的那部分数据,从而避免服务器端重新发送所有数据。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Range <20>ֶΣ<D6B6>Ȼ<EFBFBD><C8BB>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>Χ<EFBFBD><CEA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Range : bytes = 5001-10000<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 206 Partial Content ״̬<EFBFBD><EFBFBD>
|
||||
在请求报文首部中添加 Range 字段,然后指定请求的范围,例如 Range : bytes = 5001-10000。请求成功的话服务器发送 206 Partial Content 状态。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><EFBFBD>
|
||||
## 内容协商
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>̷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD>滹<EFBFBD><EFBFBD>Ӣ<EFBFBD>Ľ<EFBFBD><EFBFBD>档
|
||||
通过内容协商返回最合适的内容,例如根据浏览器的默认语言选择返回中文界面还是英文界面。
|
||||
|
||||
<EFBFBD>漰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><EFBFBD>ֶΣ<EFBFBD>Accept<EFBFBD><EFBFBD>Accept-Charset<EFBFBD><EFBFBD>Accept-Encoding<EFBFBD><EFBFBD>Accept-Language<EFBFBD><EFBFBD>Content-Language<EFBFBD><EFBFBD>
|
||||
涉及以下首部字段:Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 虚拟主机
|
||||
|
||||
ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>һ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
使用虚拟主机技术,使得一台服务器拥有多个域名,并且在逻辑上可以看成多个服务器。
|
||||
|
||||
## ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>
|
||||
## 通信数据转发
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**代理**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܿͻ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD> URL<EFBFBD><EFBFBD>
|
||||
代理服务器接受客户端的请求,并且转发给其它服务器。代理服务器一般是透明的,不会改变 URL。
|
||||
|
||||
ʹ<EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪĿ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>桢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><EFBFBD>
|
||||
使用代理的主要目的是:缓存、网络访问控制以及记录访问日志。
|
||||
|
||||

|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**网关**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ὣ HTTP ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ţ<EFBFBD><C5A3>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
与代理服务器不同的是,网关服务器会将 HTTP 转化为其它协议进行通信,从而请求其它非 HTTP 服务器的服务。
|
||||
|
||||

|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**隧道**
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> SSL <EFBFBD>ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΣ<EFBFBD>Ϊ<EFBFBD>ͻ<EFBFBD><EFBFBD>˺ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>佨<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>
|
||||
使用 SSL 等加密手段,为客户端和服务器之间建立一条安全的通信线路。
|
||||
|
||||

|
||||

|
||||
|
||||
# HTTPs
|
||||
|
||||
HTTP <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>°<EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣺
|
||||
HTTP 有以下安全性问题:
|
||||
|
||||
1. ͨ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>ܻᱻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>αװ<EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۸ġ<EFBFBD>
|
||||
1. 通信使用明文,内容可能会被窃听;
|
||||
2. 不验证通信方的身份,因此有可能遭遇伪装;
|
||||
3. 无法证明报文的完整性,所以有可能已遭篡改。
|
||||
|
||||
HTTPs <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP <EFBFBD>Ⱥ<EFBFBD> SSL<EFBFBD><EFBFBD>Secure Socket Layer<EFBFBD><EFBFBD>ͨ<EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SSL <EFBFBD><EFBFBD> TCP ͨ<EFBFBD>š<EFBFBD>ͨ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> SSL<EFBFBD><EFBFBD>HTTPs <EFBFBD>ṩ<EFBFBD>˼<EFBFBD><EFBFBD>ܡ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
HTTPs 并不是新协议,而是 HTTP 先和 SSL(Secure Socket Layer)通信,再由 SSL 和 TCP 通信。通过使用 SSL,HTTPs 提供了加密、认证和完整性保护。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 加密
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ּ<EFBFBD><EFBFBD>ܷ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD><EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܵļ<EFBFBD><EFBFBD>ܺͽ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD>ܺͽ<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD>ֱ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><EFBFBD>ã<EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD>շ<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ֮<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD><EFBFBD>յ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD>ʹ<EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
有两种加密方式:对称密钥加密和公开密钥加密。对称密钥加密的加密和解密使用同一密钥,而公开密钥加密使用一对密钥用于加密和解密,分别为公开密钥和私有密钥。公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。
|
||||
|
||||
<EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD>ȱ<EFBFBD>㣺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD>ȱ<EFBFBD>㣺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
|
||||
对称密钥加密的缺点:无法安全传输密钥;公开密钥加密的缺点:相对来说更耗时。
|
||||
|
||||
HTTPs <EFBFBD><EFBFBD><EFBFBD><EFBFBD> **<EFBFBD><EFBFBD><EFBFBD>ϵļ<EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD>**<2A><>ʹ<EFBFBD>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>Գ<EFBFBD><D4B3><EFBFBD>Կ<EFBFBD><D4BF>֮<EFBFBD><D6AE>ʹ<EFBFBD>öԳ<C3B6><D4B3><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD>ܽ<EFBFBD><DCBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD><C5A1><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD>Գ<EFBFBD><D4B3><EFBFBD>Կ<EFBFBD><D4BF>
|
||||
HTTPs 采用 **混合的加密机制**,使用公开密钥加密用于传输对称密钥,之后使用对称密钥加密进行通信。(下图中,共享密钥即对称密钥)
|
||||
|
||||

|
||||

|
||||
|
||||
## <EFBFBD><EFBFBD>֤
|
||||
## 认证
|
||||
|
||||
ͨ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> **֤<EFBFBD><EFBFBD>** <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD>ǿɿ<EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
通过使用 **证书** 来对通信方进行认证。证书中有公开密钥数据,如果可以验证公开密钥的确属于通信方的,那么就可以确定通信方是可靠的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CA<EFBFBD><EFBFBD>Certificate Authority<EFBFBD><EFBFBD><EFBFBD>䷢<EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ֤<EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> CA <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><D6A4>
|
||||
数字证书认证机构(CA,Certificate Authority)颁发的公开密钥证书,可以通过 CA 对其进行验证。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTPs ͨ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>鷢<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ֮<EFBFBD>Ϳ<EFBFBD><EFBFBD>Կ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
进行 HTTPs 通信时,服务器会把证书发送给客户端,客户端取得其中的公开密钥之后,就可以开始加密过程。
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> OpenSSL <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>䷢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>顣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD>ʸ÷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD>ȫ<EFBFBD>ԡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>վ<EFBFBD>İ<EFBFBD>ȫ֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡱<EFBFBD>Ⱦ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>
|
||||
使用 OpenSSL 这套开源程序,每个人都可以构建一套属于自己的认证机构,从而自己给自己颁发服务器证书。浏览器在访问该服务器时,会显示“无法确认连接安全性”或“该网站的安全证书存在问题”等警告消息。
|
||||
|
||||
<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD>װ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>dz<EFBFBD><EFBFBD>ߵİ<EFBFBD>ȫ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ʹ<EFBFBD>ÿͻ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
客户端证书需要用户自行安装,只有在业务需要非常高的安全性时才使用客户端证书,例如网上银行。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 完整性
|
||||
|
||||
SSL <EFBFBD>ṩժҪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
SSL 提供摘要功能来验证完整性。
|
||||
|
||||
# HTTP/1.0 <EFBFBD><EFBFBD> HTTP/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# HTTP/1.0 与 HTTP/1.1 的区别
|
||||
|
||||
- HTTP/1.1 Ĭ<EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>
|
||||
- HTTP/1.1 <EFBFBD>ṩ<EFBFBD>˷<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD>
|
||||
- HTTP/1.1 <EFBFBD>ṩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>ܣ<EFBFBD>
|
||||
- HTTP/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD>洦<EFBFBD><EFBFBD><EFBFBD>ֶΣ<EFBFBD>
|
||||
- HTTP/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ״̬<EFBFBD>룻
|
||||
- HTTP/1.1 默认是长连接;
|
||||
- HTTP/1.1 提供了范围请求功能;
|
||||
- HTTP/1.1 提供了虚拟主机的功能;
|
||||
- HTTP/1.1 多了一些缓存处理字段;
|
||||
- HTTP/1.1 多了一些状态码;
|
||||
|
669
notes/JVM.md
669
notes/JVM.md
@ -1,166 +1,167 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD>ڴ<EFBFBD>ģ<EFBFBD><EFBFBD>](#<23>ڴ<EFBFBD>ģ<EFBFBD><C4A3>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ](#2-java-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><EFBFBD><EFBFBD>ջ](#3-<2D><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>ջ)
|
||||
* [4. Java <EFBFBD><EFBFBD>](#4-java-<EFBFBD><EFBFBD>)
|
||||
* [5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#5-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#6-<2D><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [7. ֱ<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>](#7-ֱ<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>)
|
||||
* [1. <EFBFBD>ж<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ɻ<EFBFBD><EFBFBD><EFBFBD>](#1-<2D>ж<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ɻ<EFBFBD><C9BB><EFBFBD>)
|
||||
* [1.1 <EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD>](#11-<EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.2 <EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD>](#12-<EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#13-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3.1 ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#131-ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#132-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#133-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#134-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>](#13-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD>)
|
||||
* [内存模型](#内存模型)
|
||||
* [1. 程序计数器](#1-程序计数器)
|
||||
* [2. Java 虚拟机栈](#2-java-虚拟机栈)
|
||||
* [3. 本地方法栈](#3-本地方法栈)
|
||||
* [4. Java 堆](#4-java-堆)
|
||||
* [5. 方法区](#5-方法区)
|
||||
* [6. 运行时常量池](#6-运行时常量池)
|
||||
* [7. 直接内存](#7-直接内存)
|
||||
* [垃圾收集](#垃圾收集)
|
||||
* [1. 判断一个对象是否可回收](#1-判断一个对象是否可回收)
|
||||
* [1.1 引用计数](#11-引用计数)
|
||||
* [1.2 可达性](#12-可达性)
|
||||
* [1.3 引用类型](#13-引用类型)
|
||||
* [1.3.1 强引用](#131-强引用)
|
||||
* [1.3.2 软引用](#132-软引用)
|
||||
* [1.3.3 弱引用](#133-弱引用)
|
||||
* [1.3.4 虚引用](#134-虚引用)
|
||||
* [1.3 方法区的回收](#13-方法区的回收)
|
||||
* [1.4 finalize()](#14-finalize)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨](#2-<2D><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>㷨)
|
||||
* [2.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>㷨](#21-<2D><><EFBFBD><EFBFBD>---<2D><><EFBFBD><EFBFBD><EFBFBD>㷨)
|
||||
* [2.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨](#22-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨)
|
||||
* [2.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>㷨](#23-<2D><><EFBFBD><EFBFBD>---<2D><><EFBFBD><EFBFBD><EFBFBD>㷨)
|
||||
* [2.4 <EFBFBD>ִ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨](#24-<2D>ִ<EFBFBD><D6B4>ռ<EFBFBD><D5BC>㷨)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>)
|
||||
* [3.1 Serial <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#31-serial-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.2 ParNew <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#32-parnew-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.3 Parallel Scavenge <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#33-parallel-scavenge-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.4 Serial Old <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#34-serial-old-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.5 Parallel Old <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#35-parallel-old-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.6 CMS <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#36-cms-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.7 G1 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>](#37-g1-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.8 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ıȽ<EFBFBD>](#38-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>ıȽ<C4B1>)
|
||||
* [4. <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ղ<EFBFBD><EFBFBD><EFBFBD>](#4-<2D>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD>)
|
||||
* [4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#41-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-eden-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#42-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.3 <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#43-<2D><><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.4 <EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>](#44-<2D><>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>)
|
||||
* [4.5 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䵣<EFBFBD><EFBFBD>](#45-<2D>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>䵣<EFBFBD><E4B5A3>)
|
||||
* [4.6 Full GC <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#46-full-gc-<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.6.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> System.gc()](#461-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>-systemgc)
|
||||
* [4.6.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ䲻<EFBFBD><EFBFBD>](#462-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ䲻<D5BC><E4B2BB>)
|
||||
* [4.6.3 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䵣<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>](#463-<2D>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>䵣<EFBFBD><E4B5A3>ʧ<EFBFBD><CAA7>)
|
||||
* [4.6.4 JDK 1.7 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>ռ䲻<EFBFBD><EFBFBD>](#464-jdk-17-<2D><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4>ռ䲻<D5BC><E4B2BB>)
|
||||
* [2. 垃圾收集算法](#2-垃圾收集算法)
|
||||
* [2.1 标记 - 清除算法](#21-标记---清除算法)
|
||||
* [2.2 复制算法](#22-复制算法)
|
||||
* [2.3 标记 - 整理算法](#23-标记---整理算法)
|
||||
* [2.4 分代收集算法](#24-分代收集算法)
|
||||
* [3. 垃圾收集器](#3-垃圾收集器)
|
||||
* [3.1 Serial 收集器](#31-serial-收集器)
|
||||
* [3.2 ParNew 收集器](#32-parnew-收集器)
|
||||
* [3.3 Parallel Scavenge 收集器](#33-parallel-scavenge-收集器)
|
||||
* [3.4 Serial Old 收集器](#34-serial-old-收集器)
|
||||
* [3.5 Parallel Old 收集器](#35-parallel-old-收集器)
|
||||
* [3.6 CMS 收集器](#36-cms-收集器)
|
||||
* [3.7 G1 收集器](#37-g1-收集器)
|
||||
* [3.8 七种垃圾收集器的比较](#38-七种垃圾收集器的比较)
|
||||
* [4. 内存分配与回收策略](#4-内存分配与回收策略)
|
||||
* [4.1 优先在 Eden 分配](#41-优先在-eden-分配)
|
||||
* [4.2 大对象直接进入老年代](#42-大对象直接进入老年代)
|
||||
* [4.3 长期存活的对象进入老年代](#43-长期存活的对象进入老年代)
|
||||
* [4.4 动态对象年龄判定](#44-动态对象年龄判定)
|
||||
* [4.5 空间分配担保](#45-空间分配担保)
|
||||
* [4.6 Full GC 的触发条件](#46-full-gc-的触发条件)
|
||||
* [4.6.1 调用 System.gc()](#461-调用-systemgc)
|
||||
* [4.6.2 老年代空间不足](#462-老年代空间不足)
|
||||
* [4.6.3 空间分配担保失败](#463-空间分配担保失败)
|
||||
* [4.6.4 JDK 1.7 及以前的永久代空间不足](#464-jdk-17-及以前的永久代空间不足)
|
||||
* [4.6.5 Concurrent Mode Failure](#465-concurrent-mode-failure)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD>)
|
||||
* [1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>](#2-<2D><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ʱ<EFBFBD><CAB1>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ع<EFBFBD><EFBFBD><EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD>ع<EFBFBD><D8B9><EFBFBD>)
|
||||
* [3.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#31-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.2 <EFBFBD><EFBFBD>֤](#32-<EFBFBD><EFBFBD>֤)
|
||||
* [3.3 <EFBFBD><EFBFBD>](#33-<EFBFBD><EFBFBD>)
|
||||
* [3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#34-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.5 <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>](#35-<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>)
|
||||
* [4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#4-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#41-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#42-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.3 ˫<EFBFBD><EFBFBD>ί<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>](#43-˫<><CBAB>ί<EFBFBD><CEAF>ģ<EFBFBD><C4A3>)
|
||||
* [JVM <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#jvm-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [GC <EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#gc-<EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [GC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#gc-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [类加载机制](#类加载机制)
|
||||
* [1 类的生命周期](#1-类的生命周期)
|
||||
* [2. 类初始化时机](#2-类初始化时机)
|
||||
* [3. 类加载过程](#3-类加载过程)
|
||||
* [3.1 加载](#31-加载)
|
||||
* [3.2 验证](#32-验证)
|
||||
* [3.3 准备](#33-准备)
|
||||
* [3.4 解析](#34-解析)
|
||||
* [3.5 初始化](#35-初始化)
|
||||
* [4. 类加载器](#4-类加载器)
|
||||
* [4.1 类与类加载器](#41-类与类加载器)
|
||||
* [4.2 类加载器分类](#42-类加载器分类)
|
||||
* [4.3 双亲委派模型](#43-双亲委派模型)
|
||||
* [JVM 参数](#jvm-参数)
|
||||
* [GC 优化配置](#gc-优化配置)
|
||||
* [GC 类型设置](#gc-类型设置)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20>ڴ<EFBFBD>ģ<EFBFBD><C4A3>
|
||||
|
||||

|
||||
# 内存模型
|
||||
|
||||
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>߳<EFBFBD>˽<EFBFBD>еģ<EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>̹߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||

|
||||
|
||||
## 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
注:白色区域为线程私有的,蓝色区域为线程共享的。
|
||||
|
||||
<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD> Native <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD><D5A3><EFBFBD>
|
||||
## 1. 程序计数器
|
||||
|
||||
## 2. Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ
|
||||
记录正在执行的虚拟机字节码指令的地址(如果正在执行的是 Native 方法则为空)。
|
||||
|
||||
ÿ<EFBFBD><EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>ͬʱ<CDAC>ᴴ<EFBFBD><E1B4B4>һ<EFBFBD><D2BB>ջ֡<D5BB><D6A1><EFBFBD>ڴ洢<DAB4>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ<EFBFBD><CFA2>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD>ֱ<EFBFBD><D6B1>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD>ɵĹ<C9B5><C4B9>̣<EFBFBD><CCA3>Ͷ<EFBFBD>Ӧ<EFBFBD><D3A6>һ<EFBFBD><D2BB>ջ֡<D5BB><D6A1> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD>ջ<EFBFBD>ͳ<EFBFBD>ջ<EFBFBD>Ĺ<EFBFBD><C4B9>̡<EFBFBD>
|
||||
## 2. Java 虚拟机栈
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣<EFBFBD><EFBFBD>
|
||||
每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。
|
||||
|
||||
1. <20><><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>ȳ<EFBFBD><C8B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD> StackOverflowError <20>쳣<EFBFBD><ECB3A3>
|
||||
2. ջ<><D5BB><EFBFBD>ж<EFBFBD>̬<EFBFBD><CCAC>չʱ<D5B9><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD>뵼<EFBFBD>㹻<EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD>׳<EFBFBD> OutOfMemoryError <20>쳣<EFBFBD><ECB3A3>
|
||||
该区域可能抛出以下异常:
|
||||
|
||||
## 3. <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD>ջ
|
||||
1. 当线程请求的栈深度超过最大值,会抛出 StackOverflowError 异常;
|
||||
2. 栈进行动态扩展时如果无法申请导足够内存,会抛出 OutOfMemoryError 异常。
|
||||
|
||||
<EFBFBD><EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1>ط<EFBFBD><D8B7><EFBFBD>ջΪ<D5BB><CEAA><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 本地方法栈
|
||||
|
||||
## 4. Java <20><>
|
||||
与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ档
|
||||
## 4. Java 堆
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"GC <20><> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2>÷ִ<C3B7><D6B4>ռ<EFBFBD><D5BC>㷨<EFBFBD><E3B7A8>Java <20>ѻ<EFBFBD><D1BB><EFBFBD><EFBFBD>Էֳɣ<D6B3><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Էֳ<D4B7> Eden <20>ռ䡢From Survivor <20>ռ䡢To Survivor <20>ռ<EFBFBD><D5BC>ȣ<EFBFBD><C8A3><EFBFBD>
|
||||
所有对象实例都在这里分配内存。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> -Xmx <20><> -Xms <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>̬<EFBFBD><CCAC>չ<EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>չʧ<D5B9>ܻ<EFBFBD><DCBB>׳<EFBFBD> OutOfMemoryError <20>쳣<EFBFBD><ECB3A3>
|
||||
这块区域是垃圾收集器管理的主要区域("GC 堆 ")。现在收集器基本都是采用分代收集算法,Java 堆还可以分成:新生代和老年代(新生代还可以分成 Eden 空间、From Survivor 空间、To Survivor 空间等)。
|
||||
|
||||
## 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
不需要连续内存,可以通过 -Xmx 和 -Xms 来控制动态扩展内存大小,如果动态扩展失败会抛出 OutOfMemoryError 异常。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
## 5. 方法区
|
||||
|
||||
<EFBFBD><EFBFBD> Java <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD>ҿ<EFBFBD><D2BF>Զ<EFBFBD>̬<EFBFBD><CCAC>չ<EFBFBD><D5B9><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>չʧ<D5B9><CAA7>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD> OutOfMemoryError <20>쳣<EFBFBD><ECB3A3>
|
||||
用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD>ҪĿ<EFBFBD><EFBFBD><EFBFBD>ǶԳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>صĻ<EFBFBD><EFBFBD>պͶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>HotSpot <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
和 Java 堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常。
|
||||
|
||||
## 6. <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现,HotSpot 虚拟机把它当成永久代来进行垃圾回收。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>
|
||||
## 6. 运行时常量池
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD><EFBFBD><EFBFBD>Class <20>ļ<EFBFBD><C4BC>еij<D0B5><C4B3><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵĸ<C9B5><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3>ͻᱻ<CDBB>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
运行时常量池是方法区的一部分。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD> String <20><><EFBFBD><EFBFBD> intern() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µij<C2B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
类加载后,Class 文件中的常量池(用于存放编译期生成的各种字面量和符号引用)就会被放到这个区域。
|
||||
|
||||
## 7. ֱ<><D6B1><EFBFBD>ڴ<EFBFBD>
|
||||
在运行期间也可以用过 String 类的 intern() 方法将新的常量放入该区域。
|
||||
|
||||
<EFBFBD><EFBFBD> JDK 1.4 <20><><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD> NIO <20>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>Channel<65><6C><EFBFBD>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Buffer<65><72><EFBFBD><EFBFBD> I/O <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> Native <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬Ȼ<E6A3AC><C8BB>ͨ<EFBFBD><CDA8>һ<EFBFBD><D2BB><EFBFBD>洢<EFBFBD><E6B4A2> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DirectByteBuffer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><C3BD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<D2BB><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20>Ѻ<EFBFBD> Native <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
## 7. 直接内存
|
||||
|
||||
# <20><><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
|
||||
在 JDK 1.4 中新加入了 NIO 类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD>ͱ<EFBFBD><EFBFBD>ط<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>˽<EFBFBD>еģ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD>߳̽<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
# 垃圾收集
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20>Ѻͷ<D1BA><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收。
|
||||
|
||||
## 1. <20>ж<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ɻ<EFBFBD><C9BB><EFBFBD>
|
||||
垃圾回收主要是针对 Java 堆和方法区进行。
|
||||
|
||||
### 1.1 <20><><EFBFBD>ü<EFBFBD><C3BC><EFBFBD>
|
||||
## 1. 判断一个对象是否可回收
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧЧʱ<D0A7><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31>
|
||||
### 1.1 引用计数
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD>Ϊ 0 <20>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>ɱ<EFBFBD><C9B1><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
引用计数为 0 的对象可被回收。
|
||||
|
||||
两个对象会出现循环引用问题,此时引用计数器永远不为 0,导致 GC 收集器无法回收。
|
||||
|
||||
```java
|
||||
objA.instance = objB;
|
||||
objB.instance = objA;
|
||||
```
|
||||
|
||||
### 1.2 <EFBFBD>ɴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.2 可达性
|
||||
|
||||
ͨ<EFBFBD><EFBFBD> GC Roots <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ﵽ<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>õģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是都是可用的,不可达的对象可被回收。
|
||||
|
||||
GC Roots һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
GC Roots 一般包含以下内容:
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ྲ̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
1. 虚拟机栈中引用的对象
|
||||
2. 方法区中类静态属性引用的对象
|
||||
3. 方法区中的常量引用的对象
|
||||
4. 本地方法栈中引用的对象
|
||||
|
||||
### 1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.3 引用类型
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>ж϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>ж϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>ɴ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롰<EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><EFBFBD>йء<EFBFBD>
|
||||
无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判定独享是否存活都与“引用”有关。
|
||||
|
||||
#### 1.3.1 ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 1.3.1 强引用
|
||||
|
||||
ֻҪǿ<EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
只要强引用存在,垃圾回收器永远不会回收调掉被引用的对象。
|
||||
|
||||
```java
|
||||
Object obj = new Object();
|
||||
```
|
||||
|
||||
#### 1.3.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 1.3.2 软引用
|
||||
|
||||
|
||||
<EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
非必须引用,内存溢出之前进行回收。
|
||||
|
||||
```java
|
||||
Object obj = new Object();
|
||||
@ -169,14 +170,14 @@ obj = null;
|
||||
sf.get();
|
||||
```
|
||||
|
||||
sf <EFBFBD>Ƕ<EFBFBD> obj <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>ͨ<EFBFBD><EFBFBD> sf.get() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3B1BBB1><EFBFBD>Ϊ<EFBFBD><CEAA>Ҫ<EFBFBD><D2AA><EFBFBD>յĶ<D5B5><C4B6><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> null<EFBFBD><EFBFBD>
|
||||
sf 是对 obj 的一个软引用,通过 sf.get() 方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回 null;
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>û<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>㹻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD>æ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ治<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
|
||||
|
||||
|
||||
#### 1.3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 1.3.3 弱引用
|
||||
|
||||
ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>浽<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۵<EFBFBD>ǰ<EFBFBD>ڴ<EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>㹻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᱻ<EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
只能生存到下一次垃圾收集发生之前,当垃圾收集器工作时,无论当前内存是否足够,都会被回收。
|
||||
|
||||
```java
|
||||
Object obj = new Object();
|
||||
@ -186,9 +187,9 @@ wf.get();
|
||||
wf.isEnQueued();
|
||||
```
|
||||
|
||||
#### 1.3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 1.3.4 虚引用
|
||||
|
||||
<EFBFBD>ֳ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĴ<EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>乹<EFBFBD><EFBFBD>Ӱ<EFBFBD>죬Ҳ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΨһĿ<EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>յ<EFBFBD>һ<EFBFBD><EFBFBD>ϵͳ֪ͨ<EFBFBD><EFBFBD>
|
||||
又称为幽灵引用或者幻影引用,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
|
||||
|
||||
```java
|
||||
Object obj = new Object();
|
||||
@ -198,367 +199,367 @@ pf.get();
|
||||
pf.isEnQueued();
|
||||
```
|
||||
|
||||
### 1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.3 方法区的回收
|
||||
|
||||
<EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ǶԳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>صĻ<EFBFBD><EFBFBD>պͶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ء<EFBFBD>
|
||||
在方法区主要是对常量池的回收和对类的卸载。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>صĻ<EFBFBD><EFBFBD>պͶ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||||
常量池的回收和堆中对象回收类似。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ࣬<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ᱻж<EFBFBD>أ<EFBFBD>
|
||||
类的卸载条件很多,需要满足以下三个条件,并且满足了也不一定会被卸载:
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>գ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20><><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ClassLoader <EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ա<EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD> java.lang.Class <EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κεط<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κεط<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1. 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
|
||||
2. 加载该类的 ClassLoader 已经被回收。
|
||||
3. 该类对应的 java.lang.Class 对象没有在任何地方被引用,也就无法在任何地方通过反射访问该类方法。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> -Xnoclassgc <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ء<EFBFBD>
|
||||
可以通过 -Xnoclassgc 参数来控制是否对类进行卸载。
|
||||
|
||||
<EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>÷<EFBFBD><EFBFBD>䡢<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CGLib <EFBFBD><EFBFBD> ByteCode <EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD> JSP <EFBFBD>Լ<EFBFBD> OSGo <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD> ClassLoader <EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ع<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD>Ա<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在大量使用反射、动态代理、CGLib 等 ByteCode 框架、动态生成 JSP 以及 OSGo 这类频繁自定义 ClassLoader 的场景都需要虚拟机具备类卸载功能,以保证不会出现内存溢出。
|
||||
|
||||
### 1.4 finalize()
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>Ҫִ<EFBFBD><EFBFBD> finalize() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>п<EFBFBD><D0BF>ܿ<EFBFBD><DCBF><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>ڸ÷<DAB8><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><C2B1><EFBFBD><EFBFBD>ã<EFBFBD><C3A3>Ӷ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD>Ծȡ<D4BE>
|
||||
当一个对象可被回收时,如果该对象有必要执行 finalize() 方法,那么就有可能可能通过在该方法中让对象重新被引用,从而实现自救。
|
||||
|
||||
finalize() <EFBFBD><EFBFBD><EFBFBD><EFBFBD> C++ <EFBFBD><EFBFBD><EFBFBD>鹹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD>ⲿ<EFBFBD><EFBFBD>Դ<EFBFBD>ȹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> try-finally <20>ȷ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>Ҹ÷<D2B8><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>۸߰<DBB8><DFB0><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>Ҫʹ<D2AA>á<EFBFBD>
|
||||
finalize() 类似 C++ 的虚构函数,用来做关闭外部资源等工作。但是 try-finally 等方式可以做的更好,并且该方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨
|
||||
## 2. 垃圾收集算法
|
||||
|
||||
### 2.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
### 2.1 标记 - 清除算法
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>յĶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD>ǣ<EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
将需要回收的对象进行标记,然后清除。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>㣺
|
||||
不足:
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ
|
||||
1. 标记和清除过程效率都不高
|
||||
2. 会产生大量碎片
|
||||
|
||||
֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>ڸ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD>иĽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
之后的算法都是基于该算法进行改进。
|
||||
|
||||
### 2.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
### 2.2 复制算法
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڴ滮<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬ÿ<EFBFBD><EFBFBD>ֻʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˾ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬Ȼ<EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD>ʹ<EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>롣
|
||||
主要不足是只使用了内存的一半。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD>ڴ滮<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊһ<EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD> Eden <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1> Survior <20>ռ䣬ÿ<E4A3AC><C3BF>ʹ<EFBFBD><CAB9> Eden <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Survivor<6F><72><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD> Survivor <EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵĶ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> Survivor <20>ռ<EFBFBD><D5BC>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD> Survivor<EFBFBD><EFBFBD>HotSpot <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD> Survivor <EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>Ϊ 8:1<><31><EFBFBD><EFBFBD>֤<EFBFBD><D6A4><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʴﵽ 90 %<25><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD> 10% <20>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEA3AC>ôһ<C3B4><D2BB> Survivor <20>ռ<EFBFBD><D5BC>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><D0B7>䵣<EFBFBD><E4B5A3><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀռ䡣
|
||||
现在的商业虚拟机都采用这种收集算法来回收新生代,但是并不是将内存划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survior 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另一块 Survivor 空间上,最后清理 Eden 和 Survivor。HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90 %。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,需要依赖于老年代进行分配担保,也就是借用老年代的空间。
|
||||
|
||||
### 2.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
### 2.3 标记 - 整理算法
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˱߽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ档
|
||||
让所有存活的对象都向一段移动,然后直接清理掉端边界以外的内存。
|
||||
|
||||
### 2.4 <EFBFBD>ִ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨
|
||||
### 2.4 分代收集算法
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>÷ִ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD>ڴ滮<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>
|
||||
现在的商业虚拟机采用分代收集算法,它使用了前面介绍的几种收集算法,根据对象存活周期将内存划分为几块,不同块采用适当的收集算法。
|
||||
|
||||
һ<EFBFBD>㽫 Java <EFBFBD>ѷ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
一般将 Java 堆分为新生代和老年代。
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> <20>㷨<EFBFBD><E3B7A8>
|
||||
1. 新生代使用:复制算法
|
||||
2. 老年代使用:标记 - 清理 或者 标记 - 整理 算法。
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 垃圾收集器
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HotSpot <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> 7 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD>
|
||||
以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。
|
||||
|
||||
### 3.1 Serial <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.1 Serial 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD>̵߳<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>߳̽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵȴ<EFBFBD>ʱ<EFBFBD>䡣
|
||||
它是单线程的收集器,不仅意味着只会使用一个线程进行垃圾收集工作,更重要的是它在进行垃圾收集时,必须暂停所有其他工作线程,往往造成过长的等待时间。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>Ǽ<EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>߳̽<DFB3><CCBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>ߵĵ<DFB5><C4B5>߳<EFBFBD><DFB3>ռ<EFBFBD>Ч<EFBFBD>ʡ<EFBFBD>
|
||||
它的优点是简单高效,对于单个 CPU 环境来说,由于没有线程交互的开销,因此拥有最高的单线程收集效率。
|
||||
|
||||
<EFBFBD><EFBFBD> Client Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>ʮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ٶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>ֻҪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̫Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>ܵġ<EFBFBD>
|
||||
在 Client 应用场景中,分配给虚拟机管理的内存一般来说不会很大,该收集器收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿是可以接受的。
|
||||
|
||||
### 3.2 ParNew <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.2 ParNew 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Serial <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD>̰߳汾<EFBFBD><EFBFBD>
|
||||
它是 Serial 收集器的多线程版本。
|
||||
|
||||
<EFBFBD><EFBFBD> Server ģʽ<EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Serial <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CMS <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD>
|
||||
是 Server 模式下的虚拟机首选新生代收集器,除了性能原因外,主要是因为除了 Serial 收集器,只有它能与 CMS 收集器配合工作。
|
||||
|
||||
Ĭ<EFBFBD>Ͽ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> -XX:ParallelGCThreads <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
默认开始的线程数量与 CPU 数量相同,可以使用 -XX:ParallelGCThreads 参数来设置线程数。
|
||||
|
||||
### 3.3 Parallel Scavenge <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.3 Parallel Scavenge 收集器
|
||||
|
||||
<EFBFBD>Dz<EFBFBD><EFBFBD>еĶ<EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
是并行的多线程收集器。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD>û<EFBFBD><EFBFBD>̵߳<EFBFBD>ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD>Ǵﵽһ<EFBFBD><EFBFBD><EFBFBD>ɿ<EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ռ<EFBFBD><D5BC>ʱ<EFBFBD><CAB1><EFBFBD>ı<EFBFBD>ֵ<EFBFBD><D6B5>
|
||||
其它收集器关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而它的目标是达到一个可控制的吞吐量,它被称为“吞吐量优先”收集器。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。
|
||||
|
||||
ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Խ<EFBFBD>̾<EFBFBD>Խ<EFBFBD>ʺ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ٶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD>Ч<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU ʱ<>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD><C9B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ʺ<EFBFBD><CABA>ں<EFBFBD>̨<EFBFBD><CCA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ̫<D2AA>ཻ<EFBFBD><E0BDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
|
||||
|
||||
<EFBFBD>ṩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھ<EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> -XX:MaxGCPauseMillis <20><><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1> -XX:GCTimeRatio <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪ<D6B5><CEAA><EFBFBD><EFBFBD> 0 <20><>С<EFBFBD><D0A1> 100 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><D5B1><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD>
|
||||
提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间 -XX:MaxGCPauseMillis 参数以及直接设置吞吐量大小的 -XX:GCTimeRatio 参数(值为大于 0 且小于 100 的整数)。缩短停顿时间是以牺牲吞吐量和新生代空间来换取的:新生代空间变小,垃圾回收变得频繁,导致吞吐量下降。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -XX:+UseAdaptiveSizePolicy<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ֹ<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD>-Xmn<6D><6E><EFBFBD><EFBFBD>Eden <EFBFBD><EFBFBD> Survivor <EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-XX:SurvivorRatio<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣨-XX:PretenureSizeThreshold<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ǰϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽ<EFBFBD><EFBFBD>Ϊ GC <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD>ĵ<EFBFBD><C4B5>ڲ<EFBFBD><DAB2>ԣ<EFBFBD>GC Ergonomics<63><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ParNew <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
还提供了一个参数 -XX:+UseAdaptiveSizePolicy,这是一个开关参数,打开参数后,就不需要手工指定新生代的大小(-Xmn)、Eden 和 Survivor 区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种方式称为 GC 自适应的调节策略(GC Ergonomics)。自适应调节策略也是它与 ParNew 收集器的一个重要区别。
|
||||
|
||||
### 3.4 Serial Old <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.4 Serial Old 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
Serial Old <EFBFBD><EFBFBD> Serial <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>汾<EFBFBD><EFBFBD>Ҳ<EFBFBD>Ǹ<EFBFBD> Client ģʽ<C4A3>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Server ģʽ<C4A3>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD><CDBE>
|
||||
Serial Old 是 Serial 收集器的老年代版本,也是给 Client 模式下的虚拟机使用。如果用在 Server 模式下,它有两大用途:
|
||||
|
||||
1. <EFBFBD><EFBFBD> JDK 1.5 <EFBFBD>Լ<EFBFBD>֮ǰ<EFBFBD>汾<EFBFBD><EFBFBD>Parallel Old <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Parallel Scavenge <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD>Ϊ CMS <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Concurrent Mode Failure ʱʹ<EFBFBD>á<EFBFBD>
|
||||
1. 在 JDK 1.5 以及之前版本(Parallel Old 诞生以前)中与 Parallel Scavenge 收集器搭配使用。
|
||||
2. 作为 CMS 收集器的后备预案,在并发收集发生 Concurrent Mode Failure 时使用。
|
||||
|
||||
### 3.5 Parallel Old <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.5 Parallel Old 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD> Parallel Scavenge <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>汾<EFBFBD><EFBFBD>
|
||||
是 Parallel Scavenge 收集器的老年代版本。
|
||||
|
||||
<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD> CPU <20><>Դ<EFBFBD><D4B4><EFBFBD>еij<D0B5><C4B3>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȿ<EFBFBD><C8BF><EFBFBD> Parallel Scavenge <EFBFBD><EFBFBD> Parallel Old <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在注重吞吐量以及 CPU 资源敏感的场合,都可以优先考虑 Parallel Scavenge 加 Parallel Old 收集器。
|
||||
|
||||
### 3.6 CMS <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.6 CMS 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
CMS<EFBFBD><EFBFBD>Concurrent Mark Sweep<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Mark Sweep <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> <20>㷨ʵ<E3B7A8>ֵġ<D6B5>
|
||||
CMS(Concurrent Mark Sweep),从 Mark Sweep 可以知道它是基于 标记 - 清除 算法实现的。
|
||||
|
||||
<EFBFBD>ص㣺<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>١<EFBFBD>
|
||||
特点:并发收集、低停顿。
|
||||
|
||||
<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD>
|
||||
分为以下四个流程:
|
||||
|
||||
1. <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> GC Roots <20><>ֱ<EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȺܿ죬<DCBF><ECA3AC>Ҫͣ<D2AA>١<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC Roots Tracing <EFBFBD>Ĺ<EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͣ<EFBFBD>١<EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>ǣ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䶯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>Ǽ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͣ<EFBFBD>١<EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͣ<EFBFBD>١<EFBFBD>
|
||||
1. 初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿。
|
||||
2. 并发标记:进行 GC Roots Tracing 的过程,它在整个回收过程中耗时最长,不需要停顿。
|
||||
3. 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿。
|
||||
4. 并发清除:不需要停顿。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>ʱ<EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǺͲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>߳<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>١<EFBFBD>
|
||||
在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD>㣺
|
||||
具有以下缺点:
|
||||
|
||||
1. <EFBFBD><EFBFBD> CPU <EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>CMS Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD> (CPU <EFBFBD><EFBFBD><EFBFBD><EFBFBD> + 3) / 4<EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU <EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4 <20><>ʱ<EFBFBD><CAB1>CMS <20><><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD>Ϳ<EFBFBD><CDBF>ܱ<EFBFBD><DCB1>úܴ<C3BA><DCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU <20><><EFBFBD>ؾͱȽϴ<CFB4>Ҫ<EFBFBD>ֳ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥִ<C8A5><D6B4><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>̣߳<DFB3><CCA3>Ϳ<EFBFBD><CDBF>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>ٶȺ<D9B6>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 50%<25><><EFBFBD><EFBFBD>ʵҲ<CAB5><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD>ܡ<EFBFBD><DCA1><EFBFBD><EFBFBD>ҵ<EFBFBD>ͣ<EFBFBD><CDA3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>۵ģ<DBB5><C4A3><EFBFBD><EFBFBD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>͡<EFBFBD>
|
||||
1. 对 CPU 资源敏感。CMS 默认启动的回收线程数是 (CPU 数量 + 3) / 4,当 CPU 不足 4 个时,CMS 对用户程序的影响就可能变得很大,如果本来 CPU 负载就比较大,还要分出一半的运算能力去执行收集器线程,就可能导致用户程序的执行速度忽然降低了 50%,其实也让人无法接受。并且低停顿时间是以牺牲吞吐量为代价的,导致 CPU 利用率变低。
|
||||
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>̻߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD>ǹ<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>CMS <20><EFBFBD><DEB7>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> GC ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><D7B6>û<EFBFBD><C3BB>̻߳<DFB3><CCBB><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>У<EFBFBD><D0A3><EFBFBD>Ҳ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>ҪԤ<D2AA><D4A4><EFBFBD><EFBFBD><EFBFBD>㹻<EFBFBD><E3B9BB><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>û<EFBFBD><C3BB>߳<EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><C8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ҪԤ<D2AA><D4A4>һ<EFBFBD><D2BB><EFBFBD>ֿռ<D6BF><D5BC>ṩ<EFBFBD><E1B9A9><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> -XX:CMSInitiatingOccupancyFraction <20><>ֵ<EFBFBD><D6B5><EFBFBD>ı䴥<C4B1><E4B4A5><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ռ<EFBFBD>ðٷֱȣ<D6B1>JDK 1.5 Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD>ֵΪ 68<36><38>Ҳ<EFBFBD><D2B2><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD> 68% <20>Ŀռ<C4BF>֮<EFBFBD><D6AE><EFBFBD>ᴥ<EFBFBD><E1B4A5><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>õ<EFBFBD>̫<EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD><EFBFBD>¸<EFBFBD><C2B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD>棬<EFBFBD><E6A3AC>ô<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> Concurrent Mode Failure<72><65><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> Serial Old <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>
|
||||
2. 无法处理浮动垃圾。由于并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生。这一部分垃圾出现在标记过程之后,CMS 无法在当次收集中处理掉它们,只好留到下一次 GC 时再清理掉,这一部分垃圾就被称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此它不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。可以使用 -XX:CMSInitiatingOccupancyFraction 的值来改变触发收集器工作的内存占用百分比,JDK 1.5 默认设置下该值为 68,也就是当老年代使用了 68% 的空间之后会触发收集器工作。如果该值设置的太高,导致浮动垃圾无法保存,那么就会出现 Concurrent Mode Failure,此时虚拟机将启动后备预案:临时启用 Serial Old 收集器来重新进行老年代的垃圾收集。
|
||||
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><E3B7A8><EFBFBD>µĿռ<C4BF><D5BC><EFBFBD>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><DCB4>鷳<EFBFBD><E9B7B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʣ<EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><DEB7>ҵ<EFBFBD><D2B5>㹻<EFBFBD><E3B9BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䵱ǰ<E4B5B1><C7B0><EFBFBD><EFBFBD><F3A3ACB2>ò<EFBFBD><C3B2><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Full GC<EFBFBD><EFBFBD>
|
||||
3. 标记 - 清除算法导致的空间碎片,给大对象分配带来很大麻烦,往往出现老年代空间剩余,但无法找到足够大连续空间来分配当前对象,不得不提前出发一次 Full GC。
|
||||
|
||||
### 3.7 G1 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.7 G1 收集器
|
||||
|
||||

|
||||

|
||||
|
||||
G1<EFBFBD><EFBFBD>Garbage-First<EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD>ǰ<EFBFBD>صijɹ<EFBFBD>֮һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>HotSpot <20><><EFBFBD><EFBFBD><EFBFBD>ŶӸ<C5B6><D3B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>ǣ<EFBFBD><C7A3>ڱȽϳ<C8BD><CFB3>ڵģ<DAB5>δ<EFBFBD><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻<EFBFBD><E6BBBB> JDK 1.5 <20>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD> CMS <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
G1(Garbage-First)收集器是当今收集器技术发展最前沿的成果之一,它是一款面向服务端应用的垃圾收集器,HotSpot 开发团队赋予它的使命是(在比较长期的)未来可以替换掉 JDK 1.5 中发布的 CMS 收集器。
|
||||
|
||||
<EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص㣺
|
||||
具备如下特点:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>벢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>ʹ<EFBFBD>ö<EFBFBD><C3B6><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ʱ<EFBFBD>䣻
|
||||
- <EFBFBD>ִ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͼ<EFBFBD><EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC <20>ѣ<EFBFBD><D1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD>ò<EFBFBD>ͬ<EFBFBD><CDAC>ʽȥ<CABD><C8A5><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD>һ<EFBFBD><D2BB>ʱ<EFBFBD>䡢<EFBFBD><E4A1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC <20>ľɶ<C4BE><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>õ<EFBFBD><C3B5>ռ<EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
|
||||
- <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>ڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨ʵ<E3B7A8>ֵ<EFBFBD><D6B5>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӿֲ<D3BE><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Region ֮<>䣩<EFBFBD><E4A3A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD>ơ<EFBFBD><C6A1>㷨ʵ<E3B7A8>ֵģ<D6B5><C4A3><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ䲻<DABC><E4B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD><D5BC><EFBFBD>Ƭ<EFBFBD><C6AC>
|
||||
- <EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>٣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CMS <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> G1 <EFBFBD><EFBFBD> CMS <EFBFBD><EFBFBD>ͬ<EFBFBD>Ĺ<EFBFBD>ע<EFBFBD>㣬<EFBFBD><EFBFBD> G1 <20><><EFBFBD>˽<EFBFBD><CBBD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>⣬<EFBFBD><E2A3AC><EFBFBD>ܽ<EFBFBD><DCBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ʱ<EFBFBD><CAB1>ģ<EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷָ<C8B7><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ M <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC <20>ϵ<EFBFBD>ʱ<EFBFBD>䲻<EFBFBD>ó<EFBFBD><C3B3><EFBFBD> N <20><><EFBFBD>룬<EFBFBD>⼸<EFBFBD><E2BCB8><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD>ʵʱ Java<EFBFBD><EFBFBD>RTSJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD>
|
||||
- 并行与并发:能充分利用多 CPU 环境下的硬件优势,使用多个 CPU 来缩短停顿时间;
|
||||
- 分代收集:分代概念依然得以保留,虽然它不需要其它收集器配合就能独立管理整个 GC 堆,但它能够采用不同方式去处理新创建的对象和已存活一段时间、熬过多次 GC 的旧对象来获取更好的收集效果。
|
||||
- 空间整合:整体来看是基于“标记 - 整理”算法实现的收集器,从局部(两个 Region 之间)上来看是基于“复制”算法实现的,这意味着运行期间不会产生内存空间碎片。
|
||||
- 可预测的停顿:这是它相对 CMS 的一大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了降低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在 GC 上的时间不得超过 N 毫秒,这几乎已经是实时 Java(RTSJ)的垃圾收集器的特征了。
|
||||
|
||||
<EFBFBD><EFBFBD> G1 ֮ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>ķ<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> G1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Java <20>ѵ<EFBFBD><D1B5>ڴ沼<DAB4><E6B2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>кܴ<D0BA><DCB4><EFBFBD><EFBFBD>𣬽<EFBFBD><F0A3ACBD><EFBFBD><EFBFBD><EFBFBD> Java <20>ѻ<EFBFBD><D1BB><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>ȵĶ<C8B5><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Region<6F><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EEA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD> Region<6F><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ϡ<EFBFBD>
|
||||
在 G1 之前的其他收集器进行收集的范围都是整个新生代或者老生代,而 G1 不再是这样,Java 堆的内存布局与其他收集器有很大区别,将整个 Java 堆划分为多个大小相等的独立区域(Region)。虽然还保留新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,而都是一部分 Region(不需要连续)的集合。
|
||||
|
||||
֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ģ<EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>мƻ<EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20><><EFBFBD>н<EFBFBD><D0BD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD><D9B8><EFBFBD> Region <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѻ<EFBFBD><D1BB>ļ<EFBFBD>ֵ<EFBFBD><D6B5>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĿռ<C4BF><D5BC><EFBFBD>С<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ľ<EFBFBD><C4BE><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>̨ά<CCA8><CEAC>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ÿ<EFBFBD>θ<EFBFBD><CEB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD>Ȼ<EFBFBD><C8BB>ռ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Region<6F><6E><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD> Garbage-First <20><><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> Region <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD><D5BC>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>շ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ڿ<EFBFBD><DABF>Ի<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>ܸߵ<DCB8><DFB5>ռ<EFBFBD>Ч<EFBFBD>ʡ<EFBFBD>
|
||||
之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个 Java 堆中进行全区域的垃圾收集。它跟踪各个 Region 里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region(这也就是 Garbage-First 名称的来由)。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了它在有限的时间内可以获取尽可能高的收集效率。
|
||||
|
||||
Region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD> Region <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɴ<EFBFBD><C9B4>Է<EFBFBD><D4B7><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫɨ<D2AA><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20>Ѳ<EFBFBD><D1B2>ܱ<EFBFBD>֤ȷ<D7BC>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD>Ƕ<EFBFBD> GC Ч<>ʵļ<CAB5><C4BC><EFBFBD><EFBFBD>˺<EFBFBD><CBBA><EFBFBD>Ϊ<EFBFBD>˱<EFBFBD><CBB1><EFBFBD>ȫ<EFBFBD><C8AB>ɨ<EFBFBD><C9A8><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF> Region <20><>ά<EFBFBD><CEAC><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>֮<EFBFBD><D6AE>Ӧ<EFBFBD><D3A6> Remembered Set<65><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD>ڶ<EFBFBD> Reference <20><><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Write Barrier <20><>ʱ<EFBFBD>ж<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Reference <20><><EFBFBD>õĶ<C3B5><C4B6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD><CDAC> Region ֮<>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD>ͨ<EFBFBD><CDA8> CardTable <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Region <EFBFBD><EFBFBD> Remembered Set ֮<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ö<EFBFBD>ٷ<EFBFBD>Χ<EFBFBD>м<EFBFBD><D0BC><EFBFBD> Remembered Set <20><><EFBFBD>ɱ<EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>ɨ<EFBFBD><C9A8>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>©<EFBFBD><C2A9>
|
||||
Region 不可能是孤立的,一个对象分配在某个 Region 中,可以与整个 Java 堆任意的对象发生引用关系。在做可达性分析确定对象是否存活的时候,需要扫描整个 Java 堆才能保证准确性,这显然是对 GC 效率的极大伤害。为了避免全堆扫描的发生,每个 Region 都维护了一个与之对应的 Remembered Set。虚拟机发现程序在对 Reference 类型的数据进行写操作时,会产生一个 Write Barrier 暂时中断写操作,检查 Reference 引用的对象是否处于不同的 Region 之中,如果是,便通过 CardTable 把相关引用信息记录到被引用对象所属的 Region 的 Remembered Set 之中。当进行内存回收时,在 GC 根节点的枚举范围中加入 Remembered Set 即可保证不对全堆扫描也不会有遗漏。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD> Remembered Set <EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>G1 <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿ɻ<C2BF><C9BB><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>裺
|
||||
如果不计算维护 Remembered Set 的操作,G1 收集器的运作大致可划分为以下几个步骤:
|
||||
|
||||
1. <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><EFBFBD>ǣ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䶯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>Ǽ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>̵߳<EFBFBD> Remembered Set Logs <EFBFBD><EFBFBD><EFBFBD>棬<EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> Remembered Set Logs <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺϲ<EFBFBD><EFBFBD><EFBFBD> Remembered Set <EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͣ<EFBFBD><EFBFBD><EFBFBD>̣߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿɲ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>С<EFBFBD>
|
||||
4. ɸѡ<EFBFBD><EFBFBD><EFBFBD>գ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȶԸ<EFBFBD><EFBFBD><EFBFBD> Region <20>еĻ<D0B5><C4BB>ռ<EFBFBD>ֵ<EFBFBD>ͳɱ<CDB3><C9B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2A3ACB8><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GC ͣ<><CDA3><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD>ռƻ<D5BC><C6BB><EFBFBD><EFBFBD>˽<CBBD><D7B6><EFBFBD>ʵҲ<CAB5><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊֻ<CEAA><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD> Region<6F><6E>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ɿ<EFBFBD><C9BF>Ƶģ<C6B5><C4A3><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>û<EFBFBD><C3BB>߳̽<DFB3><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>Ч<EFBFBD>ʡ<EFBFBD>
|
||||
1. 初始标记
|
||||
2. 并发标记
|
||||
3. 最终标记:为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程的 Remembered Set Logs 里面,最终标记阶段需要把 Remembered Set Logs 的数据合并到 Remembered Set 中。这阶段需要停顿线程,但是可并行执行。
|
||||
4. 筛选回收:首先对各个 Region 中的回收价值和成本进行排序,根据用户所期望的 GC 停顿是时间来制定回收计划。此阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的,而且停顿用户线程将大幅度提高收集效率。
|
||||
|
||||
### 3.8 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ıȽ<EFBFBD>
|
||||
### 3.8 七种垃圾收集器的比较
|
||||
|
||||
| <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD> or <20><><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> / <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD>㷨 | Ŀ<EFBFBD><EFBFBD> | <20><><EFBFBD>ó<EFBFBD><C3B3><EFBFBD> |
|
||||
| 收集器 | 串行、并行 or 并发 | 新生代 / 老年代 | 算法 | 目标 | 适用场景 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Serial** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD>㷨 | <20><>Ӧ<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD><EFBFBD> CPU <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD> Client ģʽ |
|
||||
| **Serial Old** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> | <20><>Ӧ<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD><EFBFBD> CPU <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD> Client ģʽ<EFBFBD><EFBFBD>CMS <20>ĺ<EFBFBD><C4BA><EFBFBD>Ԥ<EFBFBD><D4A4> |
|
||||
| **ParNew** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD>㷨 | <20><>Ӧ<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> | <EFBFBD><EFBFBD> CPU <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> Server ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> CMS <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| **Parallel Scavenge** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD>㷨 | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20>ں<EFBFBD>̨<EFBFBD><CCA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ̫<D2AA>ཻ<EFBFBD><E0BDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| **Parallel Old** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20>ں<EFBFBD>̨<EFBFBD><CCA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ̫<D2AA>ཻ<EFBFBD><E0BDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| **CMS** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> | <20><>Ӧ<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB><EFBFBD><EFBFBD><EFBFBD>վ<EFBFBD><D5BE> B/S ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD> Java Ӧ<EFBFBD><EFBFBD> |
|
||||
| **G1** | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | both | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD> + <20><><EFBFBD><EFBFBD><EFBFBD>㷨 | <20><>Ӧ<EFBFBD>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻 CMS |
|
||||
| **Serial** | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单 CPU 环境下的 Client 模式 |
|
||||
| **Serial Old** | 串行 | 老年代 | 标记 - 整理 | 响应速度优先 | 单 CPU 环境下的 Client 模式、CMS 的后备预案 |
|
||||
| **ParNew** | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多 CPU 环境时在 Server 模式下与 CMS 配合 |
|
||||
| **Parallel Scavenge** | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
|
||||
| **Parallel Old** | 并行 | 老年代 | 标记 - 整理 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
|
||||
| **CMS** | 并发 | 老年代 | 标记 - 清除 | 响应速度优先 | 集中在互联网站或 B/S 系统服务端上的 Java 应用 |
|
||||
| **G1** | 并发 | both | 标记 - 整理 + 复制算法 | 响应速度优先 | 面向服务端应用,将来替换 CMS |
|
||||
|
||||
## 4. <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ղ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4. 内存分配与回收策略
|
||||
|
||||
### 4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4.1 优先在 Eden 分配
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <20><><EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><E4A3AC> Eden <20><><EFBFBD>ռ䲻<D5BC><E4B2BB>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Minor GC<EFBFBD><EFBFBD>
|
||||
大多数情况下,对象在新生代 Eden 区分配,当 Eden 区空间不够时,发起 Minor GC;
|
||||
|
||||
### 4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4.2 大对象直接进入老年代
|
||||
|
||||
<EFBFBD>ṩ -XX:PretenureSizeThreshold <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ֵ<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Survivor <EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ渴<EFBFBD>ƣ<EFBFBD>
|
||||
### 4.3 <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
提供 -XX:PretenureSizeThreshold 参数,大于此值的对象直接在老年代分配,避免在 Eden 区和 Survivor 区之间的大量内存复制;
|
||||
### 4.3 长期存活的对象进入老年代
|
||||
|
||||
JVM Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Minor GC <20><>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD> Survivor <20><><EFBFBD><EFBFBD><EFBFBD>ɵģ<C9B5><C4A3>ƶ<EFBFBD><C6B6><EFBFBD> Survivor <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Minor GC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC> 15 <20>꣬ͨ<EAA3AC><CDA8> -XX:MaxTenuringThreshold <EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD>
|
||||
JVM 为对象定义年龄计数器,经过 Minor GC 依然存活且被 Survivor 区容纳的,移动到 Survivor 区,年龄加 1,每经历一次 Minor GC 不被清理则年龄加 1,增加到一定年龄则移动到老年区(默认 15 岁,通过 -XX:MaxTenuringThreshold 设置);
|
||||
|
||||
|
||||
### 4.4 <EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
|
||||
### 4.4 动态对象年龄判定
|
||||
|
||||
<EFBFBD><EFBFBD> Survivor <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ܺʹ<EFBFBD><EFBFBD><EFBFBD> Survivor <20>ռ<EFBFBD>һ<EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
若 Survivor 区中同年龄所有对象大小总和大于 Survivor 空间一半,则年龄大于等于该年龄的对象可以直接进入老年代;
|
||||
|
||||
### 4.5 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䵣<EFBFBD><EFBFBD>
|
||||
### 4.5 空间分配担保
|
||||
|
||||
<EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD> Minor GC ֮ǰ<EFBFBD><EFBFBD>JVM <20>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ܿռ䣬<D5BC><E4A3AC><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD> Minor GC ȷ<><C8B7><EFBFBD>ǰ<EFBFBD>ȫ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><CEBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>ڵĻ<DAB5><C4BB><EFBFBD><EFBFBD><EFBFBD> Minor GC<47><43>С<EFBFBD>ڵĻ<DAB5><C4BB><EFBFBD><EFBFBD><EFBFBD> Full GC<EFBFBD><EFBFBD>
|
||||
在发生 Minor GC 之前,JVM 先检查老年代最大可用连续空间是否大于新生代所有对象总空间,成立的话 Minor GC 确认是安全的;否则继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,大于的话进行 Minor GC,小于的话进行 Full GC。
|
||||
|
||||
## 4.6 Full GC <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4.6 Full GC 的触发条件
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Minor GC<EFBFBD><EFBFBD><EFBFBD>䴥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Eden <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Minor GC<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
对于 Minor GC,其触发条件非常简单,当 Eden 区空间满时,就将触发一次 Minor GC。而 Full GC 则相对复杂,有以下条件:
|
||||
|
||||
### 4.6.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> System.gc()
|
||||
### 4.6.1 调用 System.gc()
|
||||
|
||||
<EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD> JVM <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼֻ<EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><EFBFBD> Full GC<47><43><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD> Full GC <20><>Ƶ<EFBFBD>ʣ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD>Ъ<EFBFBD><D0AA>ͣ<EFBFBD>ٵĴ<D9B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD>ܲ<EFBFBD>ʹ<EFBFBD>ô˷<C3B4><CBB7><EFBFBD><EFBFBD>Ͳ<EFBFBD>Ҫʹ<D2AA>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<DAB4><E6A3AC>ͨ<EFBFBD><CDA8> -XX:+ DisableExplicitGC <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ RMI <EFBFBD><EFBFBD><EFBFBD><EFBFBD> System.gc()<EFBFBD><EFBFBD>
|
||||
此方法的调用是建议 JVM 进行 Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加 Full GC 的频率,也即增加了间歇性停顿的次数。因此强烈建议能不使用此方法就不要使用,让虚拟机自己去管理它的内存,可通过 -XX:+ DisableExplicitGC 来禁止 RMI 调用 System.gc()。
|
||||
|
||||
### 4.6.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ䲻<EFBFBD><EFBFBD>
|
||||
### 4.6.2 老年代空间不足
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ䲻<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> Full GC <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>׳<EFBFBD><D7B3><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD> Java.lang.OutOfMemoryError: Java heap space Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC<47><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱӦ<CAB1><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD> Minor GC <20>α<D7B6><CEB1><EFBFBD><EFBFBD>ա<EFBFBD><D5A1>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ʱ<EFBFBD>估<EFBFBD><E4BCB0>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣
|
||||
老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等,当执行 Full GC 后空间仍然不足,则抛出如下错误: Java.lang.OutOfMemoryError: Java heap space 为避免以上两种状况引起的 Full GC,调优时应尽量做到让对象在 Minor GC 阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
|
||||
|
||||
### 4.6.3 <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䵣<EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>
|
||||
### 4.6.3 空间分配担保失败
|
||||
|
||||
ʹ<EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD> Minor GC <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HandlePromotionFailure <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><EFBFBD> Full GC<EFBFBD><EFBFBD>
|
||||
使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果出现了 HandlePromotionFailure 担保失败,则会触发 Full GC。
|
||||
|
||||
### 4.6.4 JDK 1.7 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>ռ䲻<EFBFBD><EFBFBD>
|
||||
### 4.6.4 JDK 1.7 及以前的永久代空间不足
|
||||
|
||||
<EFBFBD><EFBFBD> JDK 1.7 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>HotSpot <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ʵ<EFBFBD>ֵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>ŵ<EFBFBD>ΪһЩ class <20><><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD>ϵͳ<CFB5><CDB3>Ҫ<EFBFBD><D2AA><EFBFBD>ص<EFBFBD><D8B5>ࡢ<EFBFBD><E0A1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5>õķ<C3B5><C4B7><EFBFBD><EFBFBD>϶<EFBFBD>ʱ<EFBFBD><CAB1>Permanet Generation <20><><EFBFBD>ܻᱻռ<E1B1BB><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD> CMS GC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2>ִ<EFBFBD><D6B4> Full GC<47><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC <20><>Ȼ<EFBFBD><C8BB><EFBFBD>ղ<EFBFBD><D5B2>ˣ<EFBFBD><CBA3><EFBFBD>ô JVM <20><><EFBFBD>׳<EFBFBD><D7B3><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>java.lang.OutOfMemoryError: PermGen space Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> PermGen ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC <EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><EFBFBD>õķ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> PermGen <20>ռ<EFBFBD><D5BC><EFBFBD>תΪʹ<CEAA><CAB9> CMS GC<EFBFBD><EFBFBD>
|
||||
在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 class 的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation 可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么 JVM 会抛出如下错误信息:java.lang.OutOfMemoryError: PermGen space 为避免 PermGen 占满造成 Full GC 现象,可采用的方法为增大 PermGen 空间或转为使用 CMS GC。
|
||||
|
||||
<EFBFBD><EFBFBD> JDK 1.8 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ռ<EFBFBD><EFBFBD>滻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>Ԫ<EFBFBD>ռ<EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> Full GC <20><><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
在 JDK 1.8 中用元空间替换了永久代作为方法区的实现,元空间是本地内存,因此减少了一种 Full GC 触发的可能性。
|
||||
|
||||
### 4.6.5 Concurrent Mode Failure
|
||||
|
||||
ִ<EFBFBD><EFBFBD> CMS GC <EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ䲻<EFBFBD>㣨<EFBFBD><EFBFBD>ʱ<EFBFBD>ռ䲻<EFBFBD>㡱<EFBFBD><EFBFBD> CMS GC ʱ<><CAB1>ǰ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ർ<EFBFBD><E0B5BC><EFBFBD><EFBFBD>ʱ<EFBFBD>ԵĿռ䲻<D5BC>㴥<EFBFBD><E3B4A5> Full GC<47><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᱨ Concurrent Mode Failure <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Full GC<EFBFBD><EFBFBD>
|
||||
执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(有时候“空间不足”是 CMS GC 时当前的浮动垃圾过多导致暂时性的空间不足触发 Full GC),便会报 Concurrent Mode Failure 错误,并触发 Full GC。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD>
|
||||
# 类加载机制
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ䶯̬<EFBFBD><EFBFBD><EFBFBD>صġ<EFBFBD>
|
||||
类是在运行期间动态加载的。
|
||||
|
||||
## 1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 1 类的生命周期
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 7 <20><><EFBFBD>Σ<D7B6>
|
||||
包括以下 7 个阶段:
|
||||
|
||||
- **<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>Loading<EFBFBD><EFBFBD>**
|
||||
- **<EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>Verification<EFBFBD><EFBFBD>**
|
||||
- **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Preparation<EFBFBD><EFBFBD>**
|
||||
- **<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Resolution<EFBFBD><EFBFBD>**
|
||||
- **<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Initialization<EFBFBD><EFBFBD>**
|
||||
- ʹ<EFBFBD>ã<EFBFBD>Using<EFBFBD><EFBFBD>
|
||||
- ж<EFBFBD>أ<EFBFBD>Unloading<EFBFBD><EFBFBD>
|
||||
- **加载(Loading)**
|
||||
- **验证(Verification)**
|
||||
- **准备(Preparation)**
|
||||
- **解析(Resolution)**
|
||||
- **初始化(Initialization)**
|
||||
- 使用(Using)
|
||||
- 卸载(Unloading)
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ijЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¿<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>ٿ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD> Java <20>Ķ<EFBFBD>̬<EFBFBD><EFBFBD>
|
||||
其中解析过程在某些情况下可以在初始化阶段之后再开始,这是为了支持 Java 的动态绑定。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>
|
||||
## 2. 类初始化时机
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>淶<EFBFBD>в<EFBFBD>û<EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ淶<EFBFBD>ϸ<EFBFBD><EFBFBD>涨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>( <20><><EFBFBD>ء<EFBFBD><D8A1><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD> )
|
||||
虚拟机规范中并没有强制约束何时进行加载,但是规范严格规定了有且只有下列五种情况必须对类进行初始化:( 加载、验证、准备都会随着发生 )
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD> new<EFBFBD><EFBFBD>getstatic<EFBFBD><EFBFBD>putstatic<EFBFBD><EFBFBD>invokestatic <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>н<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4 <20><>ָ<EFBFBD><D6B8><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD>ǣ<EFBFBD>ʹ<EFBFBD><CAB9> new <20>ؼ<EFBFBD><D8BC><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD>ֶΣ<D6B6><CEA3><EFBFBD> final <20><><EFBFBD>Ρ<EFBFBD><CEA1><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѽ<EFBFBD><D1BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>볣<EFBFBD><EBB3A3><EFBFBD>صľ<D8B5>̬<EFBFBD>ֶγ<D6B6><CEB3>⣩<EFBFBD><E2A3A9>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>
|
||||
1. 遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类没有进行过初始化,则必须先触发其初始化。最常见的生成这 4 条指令的场景是:使用 new 关键字实例化对象的时候;读取或设置一个类的静态字段(被 final 修饰、已在编译器把结果放入常量池的静态字段除外)的时候;以及调用一个类的静态方法的时候。
|
||||
|
||||
2. ʹ<EFBFBD><EFBFBD> java.lang.reflect <EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>н<EFBFBD><EFBFBD>г<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行初始化,则需要先触发其初始化。
|
||||
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>丸<EFBFBD>û<EFBFBD>н<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>丸<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
|
||||
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>Ҫָ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Ҫִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> main() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><C7B8>ࣩ<EFBFBD><E0A3A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȳ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣻ
|
||||
4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类;
|
||||
|
||||
5. <EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> jdk1.7 <EFBFBD>Ķ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> java.lang.invoke.MethodHandle ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ REF_getStatic, REF_putStatic, REF_invokeStatic <EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>н<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
5. 当使用 jdk1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果为 REF_getStatic, REF_putStatic, REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化;
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5 <20>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ϊ<EFBFBD><CEAA>Ϊ<EFBFBD><CEAA>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>⣬<EFBFBD><E2A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><E1B4A5><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õij<C3B5><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD><EFBFBD>
|
||||
以上 5 种场景中的行为称为对一个类进行主动引用。除此之外,所有引用类的方式都不会触发初始化,称为被动引用。被动引用的常见例子包括:
|
||||
|
||||
1\. ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD>ֶΣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᵼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1\. 通过子类引用父类的静态字段,不会导致子类初始化。
|
||||
|
||||
```java
|
||||
System.out.println(SubClass.value); // value <EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD> SuperClass <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>
|
||||
System.out.println(SubClass.value); // value 字段在 SuperClass 中定义
|
||||
```
|
||||
|
||||
2\. ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鶨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD>̻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵġ<EFBFBD>ֱ<EFBFBD>Ӽ̳<EFBFBD><EFBFBD><EFBFBD> Object <20><><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժͷ<D4BA><CDB7><EFBFBD><EFBFBD><EFBFBD>
|
||||
2\. 通过数组定义来引用类,不会触发此类的初始化。该过程会对数组类进行初始化,数组类是一个由虚拟机自动生成的、直接继承自 Object 的子类,其中包含了数组的属性和方法。
|
||||
|
||||
```java
|
||||
SuperClass[] sca = new SuperClass[10];
|
||||
```
|
||||
|
||||
3\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>û<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>峣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD>ᴥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>峣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
3\. 常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
|
||||
|
||||
```java
|
||||
System.out.println(ConstClass.HELLOWORLD);
|
||||
```
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ع<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 类加载过程
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD>ء<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5 <20><><EFBFBD>Ρ<D7B6>
|
||||
包含了加载、验证、准备、解析和初始化这 5 个阶段。
|
||||
|
||||
### 3.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.1 加载
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD>ע<EFBFBD>ⲻҪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
加载是类加载的一个阶段,注意不要混淆。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ع<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
加载过程完成以下三件事:
|
||||
|
||||
1. ͨ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD>洢<EFBFBD>ṹת<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>洢<EFBFBD>ṹ<EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Class <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵķ<DDB5><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD>
|
||||
1. 通过一个类的全限定名来获取定义此类的二进制字节流。
|
||||
2. 将这个字节流所代表的静态存储结构转化为方法区的运行时存储结构。
|
||||
3. 在内存中生成一个代表这个类的 Class 对象,作为方法区这个类的各种数据的访问入口。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ʽ<EFBFBD>л<EFBFBD>ȡ<EFBFBD><EFBFBD>
|
||||
其中二进制字节流可以从以下方式中获取:
|
||||
|
||||
- <EFBFBD><EFBFBD> ZIP <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD>Ϊ<EFBFBD>պ<EFBFBD> JAR<EFBFBD><EFBFBD>EAR<EFBFBD><EFBFBD>WAR <EFBFBD><EFBFBD>ʽ<EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Applet<EFBFBD><EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD>Ƕ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> java.lang.reflect.Proxy <EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ProxyGenerator.generateProxyClass <EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> JSP Ӧ<>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD> JSP <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ɶ<EFBFBD>Ӧ<EFBFBD><D3A6> Class <EFBFBD>ࡣ
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ټ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SAP Netweaver<65><72><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>ѳ<EFBFBD><D1B3><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD><C9B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD>ķַ<C4B7><D6B7><EFBFBD>
|
||||
- 从 ZIP 包读取,这很常见,最终成为日后 JAR、EAR、WAR 格式的基础。
|
||||
- 从网络中获取,这种场景最典型的应用是 Applet。
|
||||
- 运行时计算生成,这种场景使用得最多得就是动态代理技术,在 java.lang.reflect.Proxy 中,就是用了 ProxyGenerator.generateProxyClass 的代理类的二进制字节流。
|
||||
- 由其他文件生成,典型场景是 JSP 应用,即由 JSP 文件生成对应的 Class 类。
|
||||
- 从数据库读取,这种场景相对少见,例如有些中间件服务器(如 SAP Netweaver)可以选择把程序安装到数据库中来完成程序代码在集群间的分发。
|
||||
...
|
||||
|
||||
### 3.2 <EFBFBD><EFBFBD>֤
|
||||
### 3.2 验证
|
||||
|
||||
ȷ<EFBFBD><EFBFBD> Class <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>а<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD>ȫ<EFBFBD><EFBFBD>
|
||||
确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4 <20><><EFBFBD>Σ<D7B6>
|
||||
主要有以下 4 个阶段:
|
||||
|
||||
1. <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>֤
|
||||
2. Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
3. <EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǺϷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤
|
||||
1. 文件格式验证
|
||||
2. 元数据验证(对字节码描述的信息进行语义分析)
|
||||
3. 字节码验证(通过数据流和控制流分析,确保程序语义是合法、符合逻辑的,将对类的方法体进行校验分析)
|
||||
4. 符号引用验证
|
||||
|
||||
### 3.3 <EFBFBD><EFBFBD>
|
||||
### 3.3 准备
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD> static <20><><EFBFBD>εı<CEB5><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ沢<DAB4><E6B2A2><EFBFBD>ó<EFBFBD>ʼֵ<CABC><D6B5>ʹ<EFBFBD>õ<EFBFBD><C3B5>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ档
|
||||
类变量是被 static 修饰的变量,准备阶段为类变量分配内存并设置初始值,使用的是方法区的内存。
|
||||
|
||||
ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>η<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ŷ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
实例变量不会在这阶段分配内存,它将会在对象实例化时随着对象一起分配在 Java 堆中。
|
||||
|
||||
<EFBFBD><EFBFBD>ʼֵһ<EFBFBD><EFBFBD>Ϊ 0 ֵ<><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> value <20><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>Ϊ 0 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 123<EFBFBD><EFBFBD>
|
||||
初始值一般为 0 值,例如下面的类变量 value 被初始化为 0 而不是 123。
|
||||
|
||||
```java
|
||||
public static int value = 123;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ᰴ<EFBFBD>ձ<EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD>ֵΪ 0<><30>
|
||||
如果类变量是常量,那么会按照表达式来进行初始化,而不是赋值为 0。
|
||||
|
||||
```java
|
||||
public static final int value = 123;
|
||||
```
|
||||
|
||||
### 3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.4 解析
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>صķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻Ϊֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĹ<EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
将常量池的符号引用替换为直接引用的过程。
|
||||
|
||||
### 3.5 <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
|
||||
### 3.5 初始化
|
||||
|
||||
<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
初始化阶段即虚拟机执行类构造器 <clinit>() 方法的过程。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ϵͳҪ<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʼֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>Աͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۼƻ<EFBFBD>ȥ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>
|
||||
在准备阶段,类变量已经赋过一次系统要求的初始值,而在初始化阶段,根据程序员通过程序制定的主观计划去初始化类变量和其它资源。
|
||||
|
||||
<clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص㣺
|
||||
<clinit>() 方法具有以下特点:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飨static{} <20>飩<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ļ<EFBFBD><C4BC>г<EFBFBD><D0B3>ֵ<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ܷ<EFBFBD><DCB7>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ܸ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ܷ<EFBFBD><DCB7>ʡ<EFBFBD><CAA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4>룺
|
||||
- 是由编译器自动收集类中所有类变量的赋值动作和静态语句块(static{} 块)中的语句合并产生的,编译器收集的顺序由语句在源文件中出现的顺序决定。特别注意的是,静态语句块只能访问到定义在它之前的类变量,定义在它之后的类变量只能赋值,不能访问。例如以下代码:
|
||||
|
||||
```java
|
||||
public class Test {
|
||||
static {
|
||||
i = 0; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>
|
||||
System.out.print(i); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
i = 0; // 给变量赋值可以正常编译通过
|
||||
System.out.print(i); // 这句编译器会提示“非法向前引用”
|
||||
}
|
||||
static int i = 1;
|
||||
}
|
||||
```
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>캯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <init>()<29><><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ʽ<EFBFBD>ĵ<EFBFBD><C4B5>ø<EFBFBD><C3B8><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>һ<EFBFBD><D2BB>ִ<EFBFBD><D6B4> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD>Ϊ java.lang.Object<EFBFBD><EFBFBD>
|
||||
- 与类的构造函数(或者说实例构造器 <init>())不同,不需要显式的调用父类的构造器。虚拟机会自动保证在子类的 <clinit>() 方法运行之前,父类的 <clinit>() 方法已经执行结束。因此虚拟机中第一个执行 <clinit>() 方法的类肯定为 java.lang.Object。
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><EFBFBD>룺
|
||||
- 由于父类的 <clinit>() 方法先执行,也就意味着父类中定义的静态语句块要优于子类的变量赋值操作。例如以下代码:
|
||||
|
||||
```java
|
||||
static class Parent {
|
||||
@ -573,53 +574,53 @@ static class Sub extends Parent {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(Sub.B); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>еľ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ A<><41>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD> 2
|
||||
System.out.println(Sub.B); // 输出结果是父类中的静态变量值 A,也就是 2
|
||||
}
|
||||
```
|
||||
|
||||
- <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿڲ<EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬Ҳû<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- <clinit>() 方法对于类或接口不是必须的,如果一个类中不包含静态语句块,也没有对类变量的赋值操作,编译器可以不为该类生成 <clinit>() 方法。
|
||||
|
||||
- <EFBFBD>ӿ<EFBFBD><EFBFBD>в<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>þ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD>ͬ<E0B2BB><CDAC><EFBFBD>ǣ<EFBFBD>ִ<EFBFBD>нӿڵ<D3BF> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ִ<EFBFBD>и<EFBFBD><D0B8>ӿڵ<D3BF> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ӿ<EFBFBD><D3BF>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ʹ<EFBFBD><CAB9>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ӿڲŻ<DAB2><C5BB><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD>ӿڵ<D3BF>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><CABC>ʱҲһ<D2B2><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>нӿڵ<D3BF> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 接口中不可以使用静态语句块,但仍然有类变量初始化的赋值操作,因此接口与类一样都会生成 <clinit>() 方法。但接口与类不同的是,执行接口的 <clinit>() 方法不需要先执行父接口的 <clinit>() 方法。只有当父接口中定义的变量使用时,父接口才会初始化。另外,接口的实现类在初始化时也一样不会执行接口的 <clinit>() 方法。
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᱣ֤һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD>̻߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ͬʱ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֻ࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶߳<DFB3><CCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>߳<EFBFBD>ִ<EFBFBD><D6B4> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <clinit>() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>ʱ<EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ρ<EFBFBD>
|
||||
- 虚拟机会保证一个类的 <clinit>() 方法在多线程环境下被正确的加锁和同步,如果多个线程同时初始化一个类,只会有一个线程执行这个类的 <clinit>() 方法,其它线程都会阻塞等待,直到活动线程执行 <clinit>() 方法完毕。如果在一个类的 <clinit>() 方法中有耗时的操作,就可能造成多个进程阻塞,在实际过程中此种阻塞很隐蔽。
|
||||
|
||||
## 4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4. 类加载器
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŶӰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>еġ<EFBFBD>ͨ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD> ( <20><><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> )<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿȥʵ<C8A5>֣<EFBFBD><D6A3>Ա<EFBFBD><D4B1><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ࡣʵ<E0A1A3><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流 ( 即字节码 )”这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。
|
||||
|
||||
### 4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4.1 类与类加载器
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>౾<EFBFBD><EFBFBD>һͬȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Ψһ<CEA8>ԣ<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƿռ䡣ͨ<E4A1A3><EFBFBD><D7B6>ԣ<EFBFBD><D4A3>Ƚ<EFBFBD><C8BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Class <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> equals() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>isAssignableFrom() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>isInstance() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> instanceof() <20>ؼ<EFBFBD><D8BC>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>²<EFBFBD><C2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>壬<EFBFBD><E5A3AC><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>ͬһ<CDAC><D2BB> Class <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ֻҪ<D6BB><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱض<CDB1><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。通俗而言:比较两个类是否“相等”(这里所指的“相等”,包括类的 Class 对象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回结果,也包括使用 instanceof() 关键字对做对象所属关系判定等情况),只有在这两个类时由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
|
||||
|
||||
### 4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4.2 类加载器分类
|
||||
|
||||
<EFBFBD><EFBFBD> Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĽǶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
从 Java 虚拟机的角度来讲,只存在以下两种不同的类加载器:
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Bootstrap ClassLoader<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> C++ ʵ<>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>֣<EFBFBD><D6A3><EFBFBD>һ<EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD> Java ʵ<>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><E2B2BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>̳<EFBFBD><CCB3>Գ<EFBFBD><D4B3><EFBFBD><EFBFBD><EFBFBD> java.lang.ClassLoader<EFBFBD><EFBFBD>
|
||||
一种是启动类加载器(Bootstrap ClassLoader),这个类加载器用 C++ 实现,是虚拟机自身的一部分;另一种就是所有其他类的加载器,这些类由 Java 实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader。
|
||||
|
||||
<EFBFBD><EFBFBD> Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>ĽǶȿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><EFBFBD>ֵø<EFBFBD>ϸ<EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD>
|
||||
从 Java 开发人员的角度看,类加载器可以划分得更细致一些:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Bootstrap ClassLoader<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F0BDABB4><EFBFBD><EFBFBD><EFBFBD> <JAVA_HOME>\lib Ŀ¼<EFBFBD>еģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD> -Xbootclasspath <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>еģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> rt.jar<61><72><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>⼴ʹ<E2BCB4><CAB9><EFBFBD><EFBFBD> lib Ŀ¼<C4BF><C2BC>Ҳ<EFBFBD><D2B2><EFBFBD>ᱻ<EFBFBD><E1B1BB><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>С<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD> Java <20><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3>û<EFBFBD><C3BB>ڱ<EFBFBD>д<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ѽ<EFBFBD><D1BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9> null <20><><EFBFBD>漴<EFBFBD>ɡ<EFBFBD>
|
||||
- 启动类加载器(Bootstrap ClassLoader) 此类加载器负责将存放在 <JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。 启动类加载器无法被 Java 程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,直接使用 null 代替即可。
|
||||
|
||||
- <EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Extension ClassLoader<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ExtClassLoader<EFBFBD><EFBFBD>sun.misc.Launcher$ExtClassLoader<EFBFBD><EFBFBD>ʵ<EFBFBD>ֵġ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <Java_Home>/lib/ext <EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD> java.ext.dir ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 扩展类加载器(Extension ClassLoader) 这个类加载器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将 <Java_Home>/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中,开发者可以直接使用扩展类加载器。
|
||||
|
||||
- Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Application ClassLoader<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AppClassLoader<EFBFBD><EFBFBD>sun.misc.Launcher$AppClassLoader<EFBFBD><EFBFBD>ʵ<EFBFBD>ֵġ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ClassLoader <EFBFBD>е<EFBFBD> getSystemClassLoader() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ClassPath<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 应用程序类加载器(Application ClassLoader) 这个类加载器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
|
||||
|
||||
### 4.3 ˫<EFBFBD><EFBFBD>ί<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>
|
||||
### 4.3 双亲委派模型
|
||||
|
||||
Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>صģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼչʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD>ι<EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD>ί<EFBFBD><EFBFBD>ģ<EFBFBD>ͣ<EFBFBD>Parents Delegation Model<65><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><E2A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>Լ<EFBFBD><D4BC>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>ĸ<EFBFBD><C4B8>ӹ<EFBFBD>ϵһ<CFB5><D2BB>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>Composition<6F><6E><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>ʵ<EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>̳У<CCB3>Inheritance<EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD>ϵʵ<EFBFBD>֡<EFBFBD>
|
||||
应用程序都是由三种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。下图展示的类加载器之间的层次关系,称为类加载器的双亲委派模型(Parents Delegation Model)。该模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器,这里类加载器之间的父子关系一般通过组合(Composition)关系来实现,而不是通过继承(Inheritance)的关系实现。
|
||||
|
||||

|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**工作过程**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD>ɸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>εݹ飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ն<EFBFBD>Ӧ<EFBFBD>ô<EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ֻ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɴ˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣩʱ<EFBFBD><EFBFBD><EFBFBD>Ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż᳢<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ء<EFBFBD>
|
||||
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载,而是把这个请求委派给父类加载器,每一个层次的加载器都是如此,依次递归,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成此加载请求(它搜索范围中没有找到所需类)时,子加载器才会尝试自己加载。
|
||||
|
||||
**<EFBFBD>ô<EFBFBD>**
|
||||
**好处**
|
||||
|
||||
ʹ<EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD>ί<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD>ϵ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> Java <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>߱<EFBFBD><DFB1><EFBFBD>һ<EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC>IJ<EFBFBD><C4B2>ι<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> java.lang.Object<63><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> rt.jar <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD>ն<EFBFBD><D5B6><EFBFBD>ί<EFBFBD>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD> Object <20><><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD>ࡣ<EFBFBD>෴<EFBFBD><E0B7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>˫<EFBFBD><CBAB>ί<EFBFBD><CEAF>ģ<EFBFBD>ͣ<EFBFBD><CDA3>ɸ<EFBFBD><C9B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>صĻ<D8B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>д<EFBFBD><D0B4>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>java.lang.Object <20><><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD><EFBFBD> ClassPath <20>У<EFBFBD><D0A3><EFBFBD>ϵͳ<CFB5>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC> Object <20>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><F2BDABB1><EFBFBD>һƬ<D2BB><C6AC><EFBFBD>ҡ<EFBFBD><D2A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3>Ա<EFBFBD>дһ<D0B4><D2BB><EFBFBD><EFBFBD> rt.jar <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java <20>࣬<EFBFBD><E0A3AC><EFBFBD>ᷢ<EFBFBD>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
使用双亲委派模型来组织类加载器之间的关系,使得 Java 类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类 java.lang.Object,它存放再 rt.jar 中,无论哪个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型,由各个类加载器自行加载的话,如果用户编写了一个称为`java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中将会出现多个不同的 Object 类,程序将变得一片混乱。如果开发者尝试编写一个与 rt.jar 类库中已有类重名的 Java 类,将会发现可以正常编译,但是永远无法被加载运行。
|
||||
|
||||
**ʵ<EFBFBD><EFBFBD>**
|
||||
**实现**
|
||||
|
||||
```java
|
||||
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
|
||||
@ -646,27 +647,27 @@ protected synchronized Class<?> loadClass(String name, boolean resolve) throws C
|
||||
}
|
||||
```
|
||||
|
||||
# JVM <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# JVM 参数
|
||||
|
||||
## GC <EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## GC 优化配置
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> |
|
||||
| 配置 | 描述 |
|
||||
| --- | --- |
|
||||
| -Xms | <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>С |
|
||||
| -Xmx | <EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ |
|
||||
| -Xmn | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С |
|
||||
| -XX:PermSize | <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>С |
|
||||
| -XX:MaxPermSize | <EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -Xms | 初始化堆内存大小 |
|
||||
| -Xmx | 堆内存最大值 |
|
||||
| -Xmn | 新生代大小 |
|
||||
| -XX:PermSize | 初始化永久代大小 |
|
||||
| -XX:MaxPermSize | 永久代最大容量 |
|
||||
|
||||
## GC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## GC 类型设置
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> |
|
||||
| 配置 | 描述 |
|
||||
| --- | --- |
|
||||
| -XX:+UseSerialGC | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -XX:+UseParallelGC | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -XX:+UseConcMarkSweepGC | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -XX:ParallelCMSThreads= | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = Ϊʹ<CEAA>õ<EFBFBD><C3B5>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -XX:+UseG1GC | G1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| -XX:+UseSerialGC | 串行垃圾回收器 |
|
||||
| -XX:+UseParallelGC | 并行垃圾回收器 |
|
||||
| -XX:+UseConcMarkSweepGC | 并发标记扫描垃圾回收器 |
|
||||
| -XX:ParallelCMSThreads= | 并发标记扫描垃圾回收器 = 为使用的线程数量 |
|
||||
| -XX:+UseG1GC | G1 垃圾回收器 |
|
||||
|
||||
```java
|
||||
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar java-application.jar
|
||||
|
301
notes/Java IO.md
301
notes/Java IO.md
@ -1,129 +1,130 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>̲<EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD>̲<EFBFBD><CCB2><EFBFBD>)
|
||||
* [<EFBFBD>ֽڲ<EFBFBD><EFBFBD><EFBFBD>](#<23>ֽڲ<D6BD><DAB2><EFBFBD>)
|
||||
* [<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [概览](#概览)
|
||||
* [磁盘操作](#磁盘操作)
|
||||
* [字节操作](#字节操作)
|
||||
* [字符操作](#字符操作)
|
||||
* [对象操作](#对象操作)
|
||||
* [网络操作](#网络操作)
|
||||
* [1. InetAddress](#1-inetaddress)
|
||||
* [2. URL](#2-url)
|
||||
* [3. Sockets](#3-sockets)
|
||||
* [4. Datagram](#4-datagram)
|
||||
* [NIO](#nio)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. ͨ<EFBFBD><EFBFBD><EFBFBD>뻺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#2-ͨ<><CDA8><EFBFBD>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD>)
|
||||
* [2.1 ͨ<EFBFBD><EFBFBD>](#21-ͨ<EFBFBD><EFBFBD>)
|
||||
* [2.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#22-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>)
|
||||
* [4. <EFBFBD><EFBFBD>д<EFBFBD>ļ<EFBFBD>ʵ<EFBFBD><EFBFBD>](#4-<2D><>д<EFBFBD>ļ<EFBFBD>ʵ<EFBFBD><CAB5>)
|
||||
* [5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#5-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [5.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ I/O](#51-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ-io)
|
||||
* [5.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ I/O](#52-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ-io)
|
||||
* [6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>](#6-<2D><EFBFBD><D7BD><EFBFBD>ʵ<EFBFBD><CAB5>)
|
||||
* [1. 流与块](#1-流与块)
|
||||
* [2. 通道与缓冲区](#2-通道与缓冲区)
|
||||
* [2.1 通道](#21-通道)
|
||||
* [2.2 缓冲区](#22-缓冲区)
|
||||
* [3. 缓冲区状态变量](#3-缓冲区状态变量)
|
||||
* [4. 读写文件实例](#4-读写文件实例)
|
||||
* [5. 阻塞与非阻塞](#5-阻塞与非阻塞)
|
||||
* [5.1 阻塞式 I/O](#51-阻塞式-io)
|
||||
* [5.2 非阻塞式 I/O](#52-非阻塞式-io)
|
||||
* [6. 套接字实例](#6-套接字实例)
|
||||
* [6.1 ServerSocketChannel](#61-serversocketchannel)
|
||||
* [6.2 Selectors](#62-selectors)
|
||||
* [6.3 <EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>](#63-<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>)
|
||||
* [6.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#64-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [6.5 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#65-<2D><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [6.6 ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectionKey](#66-ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-selectionkey)
|
||||
* [6.7 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O](#67-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-io)
|
||||
* [<EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [6.3 主循环](#63-主循环)
|
||||
* [6.4 监听新连接](#64-监听新连接)
|
||||
* [6.5 接受新的连接](#65-接受新的连接)
|
||||
* [6.6 删除处理过的 SelectionKey](#66-删除处理过的-selectionkey)
|
||||
* [6.7 传入的 I/O](#67-传入的-io)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><><EFBFBD><EFBFBD>
|
||||
|
||||
Java <20><> I/O <20><><EFBFBD>ſ<EFBFBD><C5BF>Էֳ<D4B7><D6B3><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
|
||||
# 概览
|
||||
|
||||
1. <20><><EFBFBD>̲<EFBFBD><CCB2><EFBFBD><EFBFBD><EFBFBD>File
|
||||
2. <20>ֽڲ<D6BD><DAB2><EFBFBD><EFBFBD><EFBFBD>InputStream <20><> OutputStream
|
||||
3. <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Reader <20><> Writer
|
||||
4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Serializable
|
||||
5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Socket
|
||||
6. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ IO<49><4F>NIO
|
||||
Java 的 I/O 大概可以分成以下几类
|
||||
|
||||
# <20><><EFBFBD>̲<EFBFBD><CCB2><EFBFBD>
|
||||
1. 磁盘操作:File
|
||||
2. 字节操作:InputStream 和 OutputStream
|
||||
3. 字符操作:Reader 和 Writer
|
||||
4. 对象操作:Serializable
|
||||
5. 网络操作:Socket
|
||||
6. 非阻塞式 IO:NIO
|
||||
|
||||
File <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD>ʾ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>ڱ<EFBFBD>ʾ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
# 磁盘操作
|
||||
|
||||
# <20>ֽڲ<D6BD><DAB2><EFBFBD>
|
||||
File 类可以用于表示文件和目录,但是它只用于表示文件的信息,而不表示文件的内容。
|
||||
|
||||

|
||||
# 字节操作
|
||||
|
||||
Java I/O ʹ<><CAB9><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>ʵ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD> InputStream Ϊ<><CEAA><EFBFBD><EFBFBD>InputStream <20>dz<EFBFBD><C7B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FileInputStream <20><> InputStream <20><><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FilterInputStream <20><><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>ߣ<EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> BufferedInputStream Ϊ FileInputStream <20>ṩ<EFBFBD><E1B9A9><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9>ܡ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB>湦<EFBFBD>ܵ<EFBFBD><DCB5>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD><D2AA> FileInputStream <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> BufferedInputStream <20><><EFBFBD>ɡ<F3BCB4BF>
|
||||

|
||||
|
||||
Java I/O 使用了装饰者模式来实现。以 InputStream 为例,InputStream 是抽象组件,FileInputStream 是 InputStream 的子类,属于具体组件,提供了字节流的输入操作。FilterInputStream 属于抽象装饰者,装饰者用于装饰组件,为组件提供额外的功能,例如 BufferedInputStream 为 FileInputStream 提供缓存的功能。实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。
|
||||
|
||||
```java
|
||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
|
||||
```
|
||||
|
||||
DataInputStream װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD>˶Ը<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> int<EFBFBD><EFBFBD>double <EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
DataInputStream 装饰者提供了对更多数据类型进行输入的操作,比如 int、double 等基本类型。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
批量读入文件中的内容到字节数组中
|
||||
|
||||
```java
|
||||
byte[] buf = new byte[20*1024];
|
||||
int bytes = 0;
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ buf.length <EFBFBD><EFBFBD><EFBFBD>ֽڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1 <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD> eof<6F><66><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>β
|
||||
// 最多读取 buf.length 个字节,返回的是实际读取的个数,返回 -1 的时候表示读到 eof,即文件尾
|
||||
while((bytes = in.read(buf, 0 , buf.length)) != -1) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
# <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 字符操作
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD>̻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>紫<EFBFBD>䣬<EFBFBD><EFBFBD>С<EFBFBD>Ĵ洢<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20><><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD>ֽڶ<D6BD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ṩ<EFBFBD><E1B9A9><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,所以 I/O 操作的都是字节而不是字符。但是在程序中操作的数据通常是字符形式,因此需要提供对字符进行操作的方法。
|
||||
|
||||
InputStreamReader ʵ<EFBFBD>ִ<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OutputStreamWriter ʵ<><CAB5><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ı<EFBFBD><C4B1>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6>̳<EFBFBD><CCB3><EFBFBD> Reader <EFBFBD><EFBFBD> Writer<EFBFBD><EFBFBD>
|
||||
InputStreamReader 实现从文本文件的字节流解码成字符流;OutputStreamWriter 实现字符流编码成为文本文件的字节流。它们都继承自 Reader 和 Writer。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ַ<EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD>ֽڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϳ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
编码就是把字符转换为字节,而解码是把字节重新组合成字符。
|
||||
|
||||
```java
|
||||
byte[] bytes = str.getBytes(encoding); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
String str = new String(bytes, encoding)<EFBFBD><EFBFBD> // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
byte[] bytes = str.getBytes(encoding); // 编码
|
||||
String str = new String(bytes, encoding); // 解码
|
||||
```
|
||||
|
||||
GBK <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ 2 <20><><EFBFBD>ֽڣ<D6BD>Ӣ<EFBFBD><D3A2>ռ 1 <20><><EFBFBD>ֽڣ<D6BD>UTF-8 <20><><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD>ռ 3 <20><><EFBFBD>ֽڣ<D6BD>Ӣ<EFBFBD><D3A2>ռ 1 <20><><EFBFBD>ֽڣ<D6BD>Java ʹ<><CAB9>˫<EFBFBD>ֽڱ<D6BD><DAB1><EFBFBD> UTF-16be<62><65><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD>Ӣ<EFBFBD>Ķ<EFBFBD>ռ 2 <20><><EFBFBD>ֽڡ<D6BD>
|
||||
GBK 编码中,中文占 2 个字节,英文占 1 个字节;UTF-8 编码中,中文占 3 个字节,英文占 1 个字节;Java 使用双字节编码 UTF-16be,中文和英文都占 2 个字节。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ò<EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD>뷽ʽ<EFBFBD><EFBFBD>ô<EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣
|
||||
如果编码和解码过程使用不同的编码方式那么就出现了乱码。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 对象操作
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD>ʹ<EFBFBD><EFBFBD>䡣
|
||||
序列化就是将一个对象转换成字节序列,方便存储和传输。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>ObjectOutputStream.writeObject()
|
||||
序列化:ObjectOutputStream.writeObject()
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>ObjectInputStream.readObject()
|
||||
反序列化:ObjectInputStream.readObject()
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʵ<EFBFBD><EFBFBD> Serializable <20>ӿڣ<D3BF><DAA3><EFBFBD>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><D7BC>û<EFBFBD><C3BB><EFBFBD>κη<CEBA><CEB7><EFBFBD><EFBFBD><EFBFBD>Ҫʵ<D2AA>֡<EFBFBD>
|
||||
序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现。
|
||||
|
||||
transient <EFBFBD>ؼ<EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD>ʹһЩ<EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD>ᱻ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>
|
||||
transient 关键字可以使一些属性不会被序列化。
|
||||
|
||||
**ArrayList <EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**<EFBFBD><EFBFBD>ArrayList <EFBFBD>д洢<EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> transient <20><><EFBFBD>εģ<CEB5><C4A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD>̬<EFBFBD><CCAC>չ<EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĿռ䶼<D5BC><E4B6BC>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>˾Ͳ<CBBE><CDB2><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>л<EFBFBD><D0BB>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5>Dz<EFBFBD><C7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
**ArrayList 序列化和反序列化的实现**:ArrayList 中存储数据的数组是用 transient 修饰的,因为这个数组是动态扩展的,并不是所有的空间都被使用,因此就不需要所有的内容都被序列化。通过重写序列化和反序列化方法,使得可以只序列化数组中有内容的那部分数据。
|
||||
|
||||
```
|
||||
private transient Object[] elementData;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 网络操作
|
||||
|
||||
Java <EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD>֣<EFBFBD>
|
||||
Java 中的网络支持:
|
||||
|
||||
1. InetAddress<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>ַ<EFBFBD><D6B7>
|
||||
2. URL<EFBFBD><EFBFBD>ͳһ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> URL <20><><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӷ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
3. Sockets<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> TCP Э<><D0AD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ţ<EFBFBD>
|
||||
4. Datagram<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> UDP Э<><D0AD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
|
||||
1. InetAddress:用于表示网络上的硬件资源,即 IP 地址;
|
||||
2. URL:统一资源定位符,通过 URL 可以直接读取或者写入网络上的数据;
|
||||
3. Sockets:使用 TCP 协议实现网络通信;
|
||||
4. Datagram:使用 UDP 协议实现网络通信。
|
||||
|
||||
## 1. InetAddress
|
||||
|
||||
û<EFBFBD>й<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD>캯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> InetAddress.getByName(String host)<EFBFBD><EFBFBD>InetAddress.getByAddress(byte[] addr)<EFBFBD><EFBFBD>
|
||||
没有公有构造函数,只能通过静态方法来创建实例,比如 InetAddress.getByName(String host)、InetAddress.getByAddress(byte[] addr)。
|
||||
|
||||
## 2. URL
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӵ<EFBFBD> URL <20>ж<EFBFBD>ȡ<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可以直接从 URL 中读取字节流数据
|
||||
|
||||
```java
|
||||
URL url = new URL("http://www.baidu.com");
|
||||
InputStream is = url.openStream(); // <EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
InputStreamReader isr = new InputStreamReader(is, "utf-8"); // <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
InputStream is = url.openStream(); // 字节流
|
||||
InputStreamReader isr = new InputStreamReader(is, "utf-8"); // 字符流
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line = br.readLine();
|
||||
while (line != null) {
|
||||
@ -137,56 +138,56 @@ is.close();
|
||||
|
||||
## 3. Sockets
|
||||
|
||||
Socket ͨ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>
|
||||
Socket 通信模型
|
||||
|
||||

|
||||

|
||||
|
||||
- ServerSocket<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- Socket<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- ServerSocket:服务器端类
|
||||
- Socket:客户端类
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳͻ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> InputStream <EFBFBD><EFBFBD> OutputStream <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
服务器和客户端通过 InputStream 和 OutputStream 进行输入输出。
|
||||
|
||||
## 4. Datagram
|
||||
|
||||
- DatagramPacket<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><EFBFBD><EFBFBD>
|
||||
- DatagramSocket<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- DatagramPacket:数据包类
|
||||
- DatagramSocket:通信类
|
||||
|
||||
# NIO
|
||||
|
||||
NIO <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> I/O <20><><EFBFBD><EFBFBD> ( <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ) ת<>ƻز<C6BB><D8B2><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>Աȥ<D4B1><C8A5><EFBFBD>ƾͿ<C6BE><CDBF>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȡ<D9B6>
|
||||
NIO 将最耗时的 I/O 操作 ( 即填充和提取缓冲区 ) 转移回操作系统,因而 不需要程序员去控制就可以极大地提高运行速度。
|
||||
|
||||
## 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 1. 流与块
|
||||
|
||||
I/O <EFBFBD><EFBFBD> NIO <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ᵽ<EFBFBD>ģ<EFBFBD>I/O <20><><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD> NIO <20>Կ<EFBFBD><D4BF>ķ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
I/O 与 NIO 最重要的区别是数据打包和传输的方式。正如前面提到的,I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O һ<><D2BB>һ<EFBFBD><D2BB><EFBFBD>ֽڽ<D6BD><DABD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD><EFBFBD>ݣ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD><EFBFBD>ݡ<EFBFBD>Ϊ<EFBFBD><CEAA>ʽ<EFBFBD><CABD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><C7B3><EFBFBD><EFBFBD>ף<EFBFBD><D7A3><EFBFBD><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><F0B5A5B8><EFBFBD><EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>Լġ<F2B5A5B5><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O ͨ<><CDA8><EFBFBD>൱<EFBFBD><E0B5B1><EFBFBD><EFBFBD>
|
||||
面向流的 I/O 一次一个字节进行处理数据,一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O ϵͳ<CFB5>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>ÿһ<C3BF><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݿ顣<DDBF><E9A1A3><EFBFBD>鴦<EFBFBD><E9B4A6><EFBFBD><EFBFBD><EFBFBD>ݱȰ<DDB1><C8B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>öࡣ<C3B6><E0A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O ȱ<><C8B1>һЩ<D2BB><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժͼ<D4BA><CDBC><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
一个面向块的 I/O 系统以块的形式处理数据,每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按流处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。
|
||||
|
||||
I/O <EFBFBD><EFBFBD><EFBFBD><EFBFBD> NIO <EFBFBD>Ѿ<EFBFBD><EFBFBD>ܺõؼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>java.io.\* <20>Ѿ<EFBFBD><D1BE><EFBFBD> NIO Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NIO <20><>һЩ<D2BB><D0A9><EFBFBD>ԡ<EFBFBD><D4A1><EFBFBD><EFBFBD>磬 java.io.\* <20><><EFBFBD>е<EFBFBD>һЩ<D2BB><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>д<EFBFBD><D0B4><EFBFBD>ݵķ<DDB5><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ü<EFBFBD>ʹ<EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>졣
|
||||
I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重新实现了,所以现在它可以利用 NIO 的一些特性。例如, java.io.\* 包中的一些类包含以块的形式读写数据的方法,这使得即使在更面向流的系统中,处理速度也会更快。
|
||||
|
||||
## 2. ͨ<EFBFBD><EFBFBD><EFBFBD>뻺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 2. 通道与缓冲区
|
||||
|
||||
### 2.1 ͨ<EFBFBD><EFBFBD>
|
||||
### 2.1 通道
|
||||
|
||||
ͨ<EFBFBD><EFBFBD> Channel <EFBFBD>Ƕ<EFBFBD>ԭ I/O <EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
通道 Channel 是对原 I/O 包中的流的模拟,可以通过它读取和写入数据。
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>֮ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD>(һ<><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> InputStream <EFBFBD><EFBFBD><EFBFBD><EFBFBD> OutputStream <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<29><> <20><>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>˫<EFBFBD><CBAB><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD>ڶ<EFBFBD>д<EFBFBD><D0B4>
|
||||
通道与流的不同之处在于,流只能在一个方向上移动,(一个流必须是 InputStream 或者 OutputStream 的子类), 而通道是双向的,可以用于读、写或者同时用于读写。
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>
|
||||
通道包括以下类型:
|
||||
|
||||
- FileChannel<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD>ж<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
- DatagramChannel<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> UDP <20><>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
- SocketChannel<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> TCP <20><>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
- ServerSocketChannel<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TCP <20><><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>ÿһ<C3BF><D2BB><EFBFBD>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>ᴴ<EFBFBD><E1B4B4>һ<EFBFBD><D2BB> SocketChannel<EFBFBD><EFBFBD>
|
||||
- FileChannel:从文件中读写数据;
|
||||
- DatagramChannel:通过 UDP 读写网络中数据;
|
||||
- SocketChannel:通过 TCP 读写网络中数据;
|
||||
- ServerSocketChannel:可以监听新进来的 TCP 连接,对每一个新进来的连接都会创建一个 SocketChannel。
|
||||
|
||||
### 2.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 2.2 缓冲区
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӷ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。也就是说,不会直接对通道进行读写数据,而是先经过缓冲区。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵĽṹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>Ķ<EFBFBD>/д<><D0B4><EFBFBD>̡<EFBFBD>
|
||||
缓冲区实质上是一个数组,但它不仅仅是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>
|
||||
缓冲区包括以下类型:
|
||||
|
||||
- ByteBuffer
|
||||
- CharBuffer
|
||||
@ -197,50 +198,50 @@ I/O
|
||||
- DoubleBuffer
|
||||
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 缓冲区状态变量
|
||||
|
||||
- capacity<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- position<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- limit<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- capacity:最大容量;
|
||||
- position:当前已经读写的字节数;
|
||||
- limit:还可以读写的字节数。
|
||||
|
||||
״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸı<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD>
|
||||
状态变量的改变过程:
|
||||
|
||||
1\. <EFBFBD>½<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>СΪ 8 <20><><EFBFBD>ֽڵĻ<DAB5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ position Ϊ 0<EFBFBD><EFBFBD><EFBFBD><EFBFBD> limit == capacity == 9<EFBFBD><EFBFBD>capacity <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1\. 新建一个大小为 8 个字节的缓冲区,此时 position 为 0,而 limit == capacity == 9。capacity 变量不会改变,下面的讨论会忽略它。
|
||||
|
||||

|
||||

|
||||
|
||||
2\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡ 3 <20><><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ʱ position <20>ƶ<EFBFBD><C6B6><EFBFBD>Ϊ 3<><33>limit <20><><EFBFBD>ֲ<EFBFBD><D6B2>䡣
|
||||
2\. 从输入通道中读取 3 个字节数据写入缓冲区中,此时 position 移动设为 3,limit 保持不变。
|
||||
|
||||

|
||||

|
||||
|
||||
3\. <EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD> flip() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> limit <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ position<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> position <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0<><30>
|
||||
3\. 在将缓冲区的数据写到输出通道之前,需要先调用 flip() 方法,这个方法将 limit 设置为当前 position,并将 position 设置为 0。
|
||||
|
||||

|
||||

|
||||
|
||||
4\. <EFBFBD>ӻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ 4 <20><><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ʱ position <EFBFBD><EFBFBD>Ϊ 4<><34>
|
||||
4\. 从缓冲区中取 4 个字节到输出缓冲中,此时 position 设为 4。
|
||||
|
||||

|
||||

|
||||
|
||||
5\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> clear() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ position <EFBFBD><EFBFBD> limit <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>á<EFBFBD>
|
||||
5\. 最后需要调用 clear() 方法来清空缓冲区,此时 position 和 limit 都被设置为最初位置。
|
||||
|
||||

|
||||

|
||||
|
||||
## 4. <EFBFBD><EFBFBD>д<EFBFBD>ļ<EFBFBD>ʵ<EFBFBD><EFBFBD>
|
||||
## 4. 读写文件实例
|
||||
|
||||
1\. ΪҪ<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileInputStream<EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> FileInputStream <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileChannel<EFBFBD><EFBFBD>
|
||||
1\. 为要读取的文件创建 FileInputStream,之后通过 FileInputStream 获取输入 FileChannel;
|
||||
|
||||
```java
|
||||
FileInputStream fin = new FileInputStream("readandshow.txt");
|
||||
FileChannel fic = fin.getChannel();
|
||||
```
|
||||
|
||||
2\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 1024 <EFBFBD><EFBFBD> Buffer
|
||||
2\. 创建一个容量为 1024 的 Buffer
|
||||
|
||||
```java
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024);
|
||||
```
|
||||
|
||||
3\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileChannel д<EFBFBD>뵽 Buffer <EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵĻ<EFBFBD><EFBFBD><EFBFBD> read() <20><><EFBFBD><EFBFBD><EFBFBD>᷵<EFBFBD><E1B7B5> -1
|
||||
3\. 将数据从输入 FileChannel 写入到 Buffer 中,如果没有数据的话, read() 方法会返回 -1
|
||||
|
||||
```java
|
||||
int r = fcin.read(buffer);
|
||||
@ -249,86 +250,86 @@ if (r == -1) {
|
||||
}
|
||||
```
|
||||
|
||||
4\. ΪҪд<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileOutputStream<EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> FileOutputStream <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileChannel
|
||||
4\. 为要写入的文件创建 FileOutputStream,之后通过 FileOutputStream 获取输出 FileChannel
|
||||
|
||||
```java
|
||||
FileOutputStream fout = new FileOutputStream("writesomebytes.txt");
|
||||
FileChannel foc = fout.getChannel();
|
||||
```
|
||||
|
||||
5\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD> flip() <EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>д
|
||||
5\. 调用 flip() 切换读写
|
||||
|
||||
```java
|
||||
buffer.flip();
|
||||
```
|
||||
|
||||
6\. <EFBFBD><EFBFBD> Buffer <EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FileChannel <EFBFBD><EFBFBD>
|
||||
6\. 把 Buffer 中的数据读取到输出 FileChannel 中
|
||||
|
||||
```java
|
||||
foc.write(buffer);
|
||||
```
|
||||
|
||||
7\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> clear() <EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
7\. 最后调用 clear() 重置缓冲区
|
||||
|
||||
```java
|
||||
buffer.clear();
|
||||
```
|
||||
|
||||
## 5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 5. 阻塞与非阻塞
|
||||
|
||||
Ӧ<EFBFBD><EFBFBD>ע<EFBFBD>⣬FileChannel <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Channel <EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
应当注意,FileChannel 不能切换到非阻塞模式,套接字 Channel 可以。
|
||||
|
||||
### 5.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ I/O
|
||||
### 5.1 阻塞式 I/O
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ I/O <20>ڵ<EFBFBD><DAB5><EFBFBD> InputStream.read() <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>һֱ<EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ż᷵<EFBFBD>أ<EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> ServerSocket.accept() <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ҳ<EFBFBD><D2B2>һֱ<D2BB><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пͻ<D0BF><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӲŻ᷵<C5BB>أ<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹ<EFBFBD><D3B9><EFBFBD><EFBFBD><EFBFBD><F3A3ACB7><EFBFBD><EFBFBD>˶<EFBFBD><CBB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>߳<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD>ÿͻ<C3BF><CDBB>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
阻塞式 I/O 在调用 InputStream.read() 方法时会一直等到数据到来时(或超时)才会返回,在调用 ServerSocket.accept() 方法时,也会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。
|
||||
|
||||

|
||||

|
||||
|
||||
### 5.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ I/O
|
||||
### 5.2 非阻塞式 I/O
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ר<EFBFBD>ŵ<EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> I/O <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
由一个专门的线程来处理所有的 I/O 事件,并负责分发。
|
||||
|
||||
<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>
|
||||
事件驱动机制:事件到的时候触发,而不是同步的去监视事件。
|
||||
|
||||
<EFBFBD>߳<EFBFBD>ͨ<EFBFBD>ţ<EFBFBD><EFBFBD>߳<EFBFBD>֮<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> wait()<EFBFBD><EFBFBD>notify() <EFBFBD>ȷ<EFBFBD>ʽͨ<EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD>֤ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>
|
||||
线程通信:线程之间通过 wait()、notify() 等方式通信,保证每次上下文切换都是有意义的,减少无谓的线程切换。
|
||||
|
||||

|
||||

|
||||
|
||||
## 6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>
|
||||
## 6. 套接字实例
|
||||
|
||||
### 6.1 ServerSocketChannel
|
||||
|
||||
ÿһ<EFBFBD><EFBFBD><EFBFBD>˿ڶ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> ServerSocketChannel <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
每一个端口都需要有一个 ServerSocketChannel 用来监听连接。
|
||||
|
||||
```java
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
ssc.configureBlocking(false); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
ssc.configureBlocking(false); // 设置为非阻塞
|
||||
|
||||
ServerSocket ss = ssc.socket();
|
||||
InetSocketAddress address = new InetSocketAddress(ports[i]);
|
||||
ss.bind(address); // <EFBFBD>˿ں<EFBFBD>
|
||||
ss.bind(address); // 绑定端口号
|
||||
```
|
||||
|
||||
### 6.2 Selectors
|
||||
|
||||
<EFBFBD>첽 I/O ͨ<EFBFBD><EFBFBD> Selector ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD> I/O <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>Ȥ <20>D <20>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵĵ<DDB5><C4B5><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><D7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵȵȣ<C8B5><C8A3>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>ʱ<EFBFBD><CAB1>ϵͳ<CFB5><CDB3><EFBFBD>ᷢ<EFBFBD><E1B7A2>֪ͨ<CDA8><D6AA>
|
||||
异步 I/O 通过 Selector 注册对特定 I/O 事件的兴趣 ― 可读的数据的到达、新的套接字连接等等,在发生这样的事件时,系统将会发送通知。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Selectors ֮<EFBFBD>Ϳ<EFBFBD><EFBFBD>ԶԲ<EFBFBD>ͬ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> register() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>register() <EFBFBD>ĵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Selector<6F><72><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OP_ACCEPT<50><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> accept <20>¼<EFBFBD><C2BC><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
|
||||
创建 Selectors 之后,就可以对不同的通道对象调用 register() 方法。register() 的第一个参数总是这个 Selector。第二个参数是 OP_ACCEPT,这里它指定我们想要监听 accept 事件,也就是在新的连接建立时所发生的事件。
|
||||
|
||||
SelectionKey <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD> Selector <20>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ᡣ<EFBFBD><E1A1A3>ij<EFBFBD><C4B3> Selector ֪ͨ<CDA8><D6AA>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>ṩ<EFBFBD><E1B9A9>Ӧ<EFBFBD>ڸ<EFBFBD><DAB8>¼<EFBFBD><C2BC><EFBFBD> SelectionKey <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еġ<EFBFBD>SelectionKey <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ᡣ
|
||||
SelectionKey 代表这个通道在此 Selector 上的这个注册。当某个 Selector 通知您某个传入事件时,它是通过提供对应于该事件的 SelectionKey 来进行的。SelectionKey 还可以用于取消通道的注册。
|
||||
|
||||
```java
|
||||
Selector selector = Selector.open();
|
||||
SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
|
||||
```
|
||||
|
||||
### 6.3 <EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>
|
||||
### 6.3 主循环
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD> Selector <EFBFBD><EFBFBD> select() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD> select() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
首先,我们调用 Selector 的 select() 方法。这个方法会阻塞,直到至少有一个已注册的事件发生。当一个或者更多的事件发生时, select() 方法将返回所发生的事件的数量。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD> Selector <EFBFBD><EFBFBD> selectedKeys() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD> SelectionKey <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> <20><><EFBFBD><EFBFBD> <20><>
|
||||
接下来,我们调用 Selector 的 selectedKeys() 方法,它返回发生了事件的 SelectionKey 对象的一个 集合 。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectionKeys <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD> SelectionKey <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿһ<EFBFBD><EFBFBD> SelectionKey<65><79><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô I/O <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD>Щ I/O <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
我们通过迭代 SelectionKeys 并依次处理每个 SelectionKey 来处理事件。对于每一个 SelectionKey,您必须确定发生的是什么 I/O 事件,以及这个事件影响哪些 I/O 对象。
|
||||
|
||||
```java
|
||||
int num = selector.select();
|
||||
@ -342,9 +343,9 @@ while (it.hasNext()) {
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 6.4 监听新连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ServerSocketChannel<65><6C><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD><C7A1><EFBFBD><EFBFBD>ա<EFBFBD><D5A1>¼<EFBFBD><C2BC><EFBFBD>Ϊȷ<CEAA><C8B7><EFBFBD><EFBFBD>һ<EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>Ƕ<EFBFBD> SelectionKey <EFBFBD><EFBFBD><EFBFBD><EFBFBD> readyOps() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鷢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʲô<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>
|
||||
程序执行到这里,我们仅注册了 ServerSocketChannel,并且仅注册它们“接收”事件。为确认这一点,我们对 SelectionKey 调用 readyOps() 方法,并检查发生了什么类型的事件:
|
||||
|
||||
```java
|
||||
if ((key.readyOps() & SelectionKey.OP_ACCEPT)
|
||||
@ -354,39 +355,39 @@ if ((key.readyOps() & SelectionKey.OP_ACCEPT)
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Կ϶<EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD> readOps() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><C7B8>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
可以肯定地说, readOps() 方法告诉我们该事件是新的连接。
|
||||
|
||||
### 6.5 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 6.5 接受新的连接
|
||||
|
||||
<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ؽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD> accept() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
因为我们知道这个服务器套接字上有一个传入连接在等待,所以可以安全地接受它;也就是说,不用担心 accept() 操作会阻塞:
|
||||
|
||||
```java
|
||||
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
|
||||
SocketChannel sc = ssc.accept();
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD> SocketChannel <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>Ϊ<EFBFBD>˶<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD>뽫 SocketChannel ע<EFBFBD>ᵽ Selector<EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>
|
||||
下一步是将新连接的 SocketChannel 配置为非阻塞的。而且由于接受这个连接的目的是为了读取来自套接字的数据,所以我们还必须将 SocketChannel 注册到 Selector上,如下所示:
|
||||
|
||||
```java
|
||||
sc.configureBlocking( false );
|
||||
SelectionKey newKey = sc.register( selector, SelectionKey.OP_READ );
|
||||
```
|
||||
|
||||
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> register() <EFBFBD><EFBFBD> OP_READ <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SocketChannel ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȡ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
注意我们使用 register() 的 OP_READ 参数,将 SocketChannel 注册用于 读取 而不是 接受 新连接。
|
||||
|
||||
### 6.6 ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectionKey
|
||||
### 6.6 删除处理过的 SelectionKey
|
||||
|
||||
<EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD> SelectionKey ֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectionKey <20><>ѡ<EFBFBD><D1A1><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD>ᵼ<EFBFBD><E1B5BC><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><C7B3><EFBFBD><EFBFBD>ٴδ<D9B4><CEB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> remove() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectionKey<EFBFBD><EFBFBD>
|
||||
在处理 SelectionKey 之后,我们几乎可以返回主循环了。但是我们必须首先将处理过的 SelectionKey 从选定的键集合中删除。如果我们没有删除处理过的键,那么它仍然会在主集合中以一个激活的键出现,这会导致我们尝试再次处理它。我们调用迭代器的 remove() 方法来删除处理过的 SelectionKey:
|
||||
|
||||
```java
|
||||
it.remove();
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20>¼<EFBFBD>)<29>ˡ<EFBFBD>
|
||||
现在我们可以返回主循环并接受从一个套接字中传入的数据(或者一个传入的 I/O 事件)了。
|
||||
|
||||
### 6.7 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O
|
||||
### 6.7 传入的 I/O
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᴥ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> I/O <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᵼ<EFBFBD><E1B5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD>е<EFBFBD><D0B5><EFBFBD> Selector.select()<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD> I/O <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD> SelectionKey <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ OP_READ <20>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>
|
||||
当来自一个套接字的数据到达时,它会触发一个 I/O 事件。这会导致在主循环中调用 Selector.select(),并返回一个或者多个 I/O 事件。这一次, SelectionKey 将被标记为 OP_READ 事件,如下所示:
|
||||
|
||||
```java
|
||||
} else if ((key.readyOps() & SelectionKey.OP_READ)
|
||||
@ -398,9 +399,9 @@ it.remove();
|
||||
```
|
||||
|
||||
|
||||
# <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 参考资料
|
||||
|
||||
- Eckel B, <EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD> , <20><><EFBFBD><EFBFBD> , <EFBFBD><EFBFBD> . Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD> [M]. <20><>е<EFBFBD><D0B5>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> , 2002.
|
||||
- [IBM: NIO <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html)
|
||||
- [ <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Java I/O <EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ](https://www.ibm.com/developerworks/cn/java/j-lo-javaio/index.html)
|
||||
- [NIO <EFBFBD>봫ͳ IO <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ](http://blog.csdn.net/shimiso/article/details/24990499)
|
||||
- Eckel B, 埃克尔 , 昊鹏 , 等 . Java 编程思想 [M]. 机械工业出版社 , 2002.
|
||||
- [IBM: NIO 入门](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html)
|
||||
- [ 深入分析 Java I/O 的工作机制 ](https://www.ibm.com/developerworks/cn/java/j-lo-javaio/index.html)
|
||||
- [NIO 与传统 IO 的区别 ](http://blog.csdn.net/shimiso/article/details/24990499)
|
||||
|
143
notes/Java 容器.md
143
notes/Java 容器.md
@ -1,78 +1,79 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [概览](#概览)
|
||||
* [1. List](#1-list)
|
||||
* [2. Set](#2-set)
|
||||
* [3. Queue](#3-queue)
|
||||
* [4. Map](#4-map)
|
||||
* [5. Java 1.0/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#5-java-1011-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#<23><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#2-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [ɢ<EFBFBD><EFBFBD>](#ɢ<EFBFBD><EFBFBD>)
|
||||
* [Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#Դ<><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [5. Java 1.0/1.1 容器](#5-java-1011-容器)
|
||||
* [容器中的设计模式](#容器中的设计模式)
|
||||
* [1. 迭代器模式](#1-迭代器模式)
|
||||
* [2. 适配器模式](#2-适配器模式)
|
||||
* [散列](#散列)
|
||||
* [源码分析](#源码分析)
|
||||
* [1. ArraList](#1-arralist)
|
||||
* [2. Vector <EFBFBD><EFBFBD> Stack](#2-vector-<EFBFBD><EFBFBD>-stack)
|
||||
* [2. Vector 与 Stack](#2-vector-与-stack)
|
||||
* [3. LinkedList](#3-linkedlist)
|
||||
* [4. TreeMap](#4-treemap)
|
||||
* [5. HashMap](#5-hashmap)
|
||||
* [6. LinkedHashMap](#6-linkedhashmap)
|
||||
* [7. ConcurrentHashMap](#7-concurrenthashmap)
|
||||
* [<EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><><EFBFBD><EFBFBD>
|
||||
|
||||

|
||||
# 概览
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Collection <20><> Map <20><><EFBFBD>֣<EFBFBD>Collection <20>ְ<EFBFBD><D6B0><EFBFBD><EFBFBD><EFBFBD> List<73><74>Set <20>Լ<EFBFBD> Queue<75><65>
|
||||

|
||||
|
||||
容器主要包括 Collection 和 Map 两种,Collection 又包含了 List、Set 以及 Queue。
|
||||
|
||||
## 1. List
|
||||
|
||||
- ArrayList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>
|
||||
- ArrayList:基于动态数组实现,支持随机访问;
|
||||
|
||||
- LinkedList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>ֻ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD>ٵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD>Ԫ<EFBFBD>ء<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>LinkedList <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD>˫<EFBFBD>˶<EFBFBD><CBB6>С<EFBFBD>
|
||||
- LinkedList:基于双向循环链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双端队列。
|
||||
|
||||
## 2. Set
|
||||
|
||||
- HashSet<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hash ʵ<>֣<EFBFBD>֧<EFBFBD>ֿ<EFBFBD><D6BF>ٲ<EFBFBD><D9B2>ң<EFBFBD><D2A3><EFBFBD><EFBFBD><EFBFBD>ʧȥ<CAA7><C8A5><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>
|
||||
- HashSet:基于 Hash 实现,支持快速查找,但是失去有序性;
|
||||
|
||||
- TreeSet<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ʲ<EFBFBD><EFBFBD><EFBFBD> HashSet<EFBFBD><EFBFBD>
|
||||
- TreeSet:基于红黑树实现,保持有序,但是查找效率不如 HashSet;
|
||||
|
||||
- LinkedListHashSet<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HashSet <EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>Ԫ<EFBFBD>صIJ<EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
- LinkedListHashSet:具有 HashSet 的查找效率,且内部使用链表维护元素的插入顺序,因此具有有序性。
|
||||
|
||||
## 3. Queue
|
||||
|
||||
ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>LinkedList <EFBFBD><EFBFBD> PriorityQueue<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> LinkedList ֧<EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>PriorityQueue <EFBFBD>ǻ<EFBFBD><EFBFBD>ڶѽṹʵ<EFBFBD>֡<EFBFBD>
|
||||
只有两个实现:LinkedList 和 PriorityQueue,其中 LinkedList 支持双向队列,PriorityQueue 是基于堆结构实现。
|
||||
|
||||
## 4. Map
|
||||
|
||||
- HashMap<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Hash ʵ<EFBFBD><EFBFBD>
|
||||
- HashMap:基于 Hash 实现
|
||||
|
||||
- LinkedHashMap<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>LRU<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>
|
||||
- LinkedHashMap:使用链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序
|
||||
|
||||
- TreeMap<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>
|
||||
- TreeMap:基于红黑树实现
|
||||
|
||||
- ConcurrentHashMap<EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ Map<61><70><EFBFBD><EFBFBD><EFBFBD>漰<EFBFBD><E6BCB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HashTable <EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- ConcurrentHashMap:线程安全 Map,不涉及类似于 HashTable 的同步加锁
|
||||
|
||||
## 5. Java 1.0/1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 5. Java 1.0/1.1 容器
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ھɵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽⡣
|
||||
对于旧的容器,我们决不应该使用它们,只需要对它们进行了解。
|
||||
|
||||
- Vector<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ArrayList <EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ<EFBFBD><EFBFBD>
|
||||
- Vector:和 ArrayList 类似,但它是线程安全的
|
||||
|
||||
- HashTable<EFBFBD><EFBFBD><EFBFBD><EFBFBD> HashMap <EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ<EFBFBD><EFBFBD>
|
||||
- HashTable:和 HashMap 类似,但它是线程安全的
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
# 容器中的设计模式
|
||||
|
||||
## 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 1. 迭代器模式
|
||||
|
||||
<EFBFBD>Ӹ<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> Iterator <20><><EFBFBD><EFBFBD><F3A3ACBF><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>Ԫ<EFBFBD>ء<EFBFBD>
|
||||
从概览图可以看到,每个集合类都有一个 Iterator 对象,可以通过这个迭代器对象来遍历集合中的元素。
|
||||
|
||||
[Java <EFBFBD>еĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ ](https://github.com/CyC2018/InterviewNotes/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md#92-java-%E5%86%85%E7%BD%AE%E7%9A%84%E8%BF%AD%E4%BB%A3%E5%99%A8)
|
||||
[Java 中的迭代器模式 ](https://github.com/CyC2018/InterviewNotes/blob/master/notes/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md#92-java-%E5%86%85%E7%BD%AE%E7%9A%84%E8%BF%AD%E4%BB%A3%E5%99%A8)
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 2. 适配器模式
|
||||
|
||||
java.util.Arrays#asList() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ List <EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
java.util.Arrays#asList() 可以把数组类型转换为 List 类型。
|
||||
|
||||
```java
|
||||
List list = Arrays.asList(1, 2, 3);
|
||||
@ -80,44 +81,44 @@ java.util.Arrays#asList()
|
||||
list = Arrays.asList(arr);
|
||||
```
|
||||
|
||||
# ɢ<EFBFBD><EFBFBD>
|
||||
# 散列
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> hasCode() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɢ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD><EFBFBD>
|
||||
使用 hasCode() 来返回散列值,使用的是对象的地址。
|
||||
|
||||
<EFBFBD><EFBFBD> equals() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɢ<EFBFBD><EFBFBD>ֵһ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɢ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
而 equals() 是用来判断两个对象是否相等的,相等的两个对象散列值一定要相同,但是散列值相同的两个对象不一定相等。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>
|
||||
相等必须满足以下五个性质:
|
||||
|
||||
1. <EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
4. һ<EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD><EFBFBD><EFBFBD> x.equals(y)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣩
|
||||
5. <EFBFBD><EFBFBD><EFBFBD>κβ<EFBFBD><EFBFBD><EFBFBD> null <20>Ķ<EFBFBD><C4B6><EFBFBD> x <20><><EFBFBD><EFBFBD> x.equals(nul) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ false
|
||||
1. 自反性
|
||||
2. 对称性
|
||||
3. 传递性
|
||||
4. 一致性(多次调用 x.equals(y),结果不变)
|
||||
5. 对任何不是 null 的对象 x 调用 x.equals(nul) 结果都为 false
|
||||
|
||||
# Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 源码分析
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD> [ <EFBFBD>㷨 - <EFBFBD><EFBFBD><EFBFBD><EFBFBD> ](https://github.com/CyC2018/InterviewNotes/blob/master/notes/%E7%AE%97%E6%B3%95.md#%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%9F%A5%E6%89%BE) <EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
建议先阅读 [ 算法 - 查找 ](https://github.com/CyC2018/InterviewNotes/blob/master/notes/%E7%AE%97%E6%B3%95.md#%E7%AC%AC%E4%B8%89%E7%AB%A0-%E6%9F%A5%E6%89%BE) 部分,对集合类源码的理解有很大帮助。
|
||||
|
||||
Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>[OpenJDK 1.7](http://download.java.net/openjdk/jdk7)
|
||||
源码下载:[OpenJDK 1.7](http://download.java.net/openjdk/jdk7)
|
||||
|
||||
## 1. ArraList
|
||||
|
||||
[ArraList.java](https://github.com/CyC2018/InterviewNotes/blob/master/notes/src/ArrayList.java)
|
||||
|
||||
ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> RandomAccess <EFBFBD>ӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>Ϊ ArrayList <20>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵġ<D6B5>
|
||||
实现了 RandomAccess 接口,因此支持随机访问,这是理所当然的,因为 ArrayList 是基于数组实现的。
|
||||
|
||||
```java
|
||||
public class ArrayList<E> extends AbstractList<E>
|
||||
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> transient <20><><EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>鲻һ<E9B2BB><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ö<EFBFBD>ռ<EFBFBD><D5BC>Ԫ<EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2>û<EFBFBD><C3BB>Ҫȫ<D2AA><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>д writeObject() <EFBFBD><EFBFBD> readObject()<EFBFBD><EFBFBD>
|
||||
基于数组实现,保存元素的数组使用 transient 修饰,这是因为该数组不一定所有位置都占满元素,因此也就没必要全部都进行序列化。需要重写 writeObject() 和 readObject()。
|
||||
|
||||
```java
|
||||
private transient Object[] elementData;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϴ<EFBFBD>СΪ 10
|
||||
数组的默认大小为 10
|
||||
|
||||
```java
|
||||
public ArrayList(int initialCapacity) {
|
||||
@ -132,7 +133,7 @@ public ArrayList() {
|
||||
}
|
||||
```
|
||||
|
||||
ɾ<EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> System.arraycopy() <EFBFBD><EFBFBD>Ԫ<EFBFBD>ؽ<EFBFBD><EFBFBD>и<EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD>ܸߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD><EFBFBD>Ʋ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
删除元素时调用 System.arraycopy() 对元素进行复制,因此删除操作成本很高,最好在创建时就指定大概的容量大小,减少复制操作的执行次数。
|
||||
|
||||
```java
|
||||
public E remove(int index) {
|
||||
@ -150,9 +151,9 @@ public E remove(int index) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ʱʹ<EFBFBD><EFBFBD> ensureCapacity() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㹻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1.5 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
添加元素时使用 ensureCapacity() 方法来保证容量足够,如果不够时,需要进行扩容,使得新容量为旧容量的 1.5 倍。
|
||||
|
||||
modCount <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼ ArrayList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊÿ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD> add() <EFBFBD><EFBFBD> addAll() ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ensureCapacity()<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ensureCapacity() <EFBFBD>ж<EFBFBD> modCount <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
modCount 用来记录 ArrayList 发生变化的次数,因为每次在进行 add() 和 addAll() 时都需要调用 ensureCapacity(),因此直接在 ensureCapacity() 中对 modCount 进行修改。
|
||||
|
||||
```java
|
||||
public void ensureCapacity(int minCapacity) {
|
||||
@ -190,7 +191,7 @@ private static int hugeCapacity(int minCapacity) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ƚϲ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD> modCount <20>Ƿ<EFBFBD><C7B7>ı䣬<C4B1><E4A3AC><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>׳<EFBFBD> ConcurrentModificationException<EFBFBD><EFBFBD>
|
||||
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。
|
||||
|
||||
```java
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
@ -213,20 +214,20 @@ private void writeObject(java.io.ObjectOutputStream s)
|
||||
}
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD> Vector <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**和 Vector 的区别**
|
||||
|
||||
1. Vector <EFBFBD><EFBFBD> ArrayList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ͬ<EFBFBD>ģ<EFBFBD>Ψһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Vector <20><>ͬ<EFBFBD><CDAC><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>˿<EFBFBD><CBBF><EFBFBD><EFBFBD>ͱ<EFBFBD> ArrayList Ҫ<><EFBFBD><F3A3ACB7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> ArrayList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Vector<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>
|
||||
2. Vector ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD> 2 <20><><EFBFBD>ռ䣬<D5BC><E4A3AC> ArrayList <EFBFBD><EFBFBD> 1.5 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1. Vector 和 ArrayList 几乎是完全相同的,唯一的区别在于 Vector 是同步的,因此开销就比 ArrayList 要大,访问要慢。最好使用 ArrayList 而不是 Vector,因为同步完全可以由程序员自己来控制;
|
||||
2. Vector 每次扩容请求其大小的 2 倍空间,而 ArrayList 是 1.5 倍。
|
||||
|
||||
Ϊ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ<EFBFBD><EFBFBD> ArrayList<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> Collections.synchronizedList(new ArrayList<>()); <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>̰߳<EFBFBD>ȫ<EFBFBD><EFBFBD> ArrayList<73><74>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> concurrent <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD> CopyOnWriteArrayList <EFBFBD>ࣻ
|
||||
为了使用线程安全的 ArrayList,可以使用 Collections.synchronizedList(new ArrayList<>()); 返回一个线程安全的 ArrayList,也可以使用 concurrent 并发包下的 CopyOnWriteArrayList 类;
|
||||
|
||||
**<EFBFBD><EFBFBD> LinkedList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**和 LinkedList 的区别**
|
||||
|
||||
1. ArrayList <EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>LinkedList <20><><EFBFBD><EFBFBD>˫<EFBFBD><CBAB>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>
|
||||
2. ArrayList ֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>LinkedList <EFBFBD><EFBFBD>֧<EFBFBD>֣<EFBFBD>
|
||||
3. LinkedList <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD>졣
|
||||
1. ArrayList 基于动态数组实现,LinkedList 基于双向循环链表实现;
|
||||
2. ArrayList 支持随机访问,LinkedList 不支持;
|
||||
3. LinkedList 在任意位置添加删除元素更快。
|
||||
|
||||
## 2. Vector <EFBFBD><EFBFBD> Stack
|
||||
## 2. Vector 与 Stack
|
||||
|
||||
[Vector.java](https://github.com/CyC2018/InterviewNotes/blob/master/notes/src/Vector.java)
|
||||
|
||||
@ -242,13 +243,13 @@ private void writeObject(java.io.ObjectOutputStream s)
|
||||
|
||||
[HashMap.java](https://github.com/CyC2018/InterviewNotes/blob/master/notes/src/HashMap.java)
|
||||
|
||||
ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>
|
||||
使用拉链法来解决冲突。
|
||||
|
||||
Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> capacity Ϊ 16<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣֤Ϊ 2 <20>Ĵη<C4B4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Entry[] table <20><><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3>ȣ<EFBFBD>size <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
默认容量 capacity 为 16,需要注意的是容量必须保证为 2 的次方。容量就是 Entry[] table 数组的长度,size 是数组的实际使用量。
|
||||
|
||||
threshold <EFBFBD>涨<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> size <20><><EFBFBD>ٽ<EFBFBD>ֵ<EFBFBD><D6B5>size <20><><EFBFBD><EFBFBD>С<EFBFBD><D0A1> threshold<6C><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>ڣ<EFBFBD><DAA3>ͱ<EFBFBD><CDB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD>
|
||||
threshold 规定了一个 size 的临界值,size 必须小于 threshold,如果大于等于,就必须进行扩容操作。
|
||||
|
||||
threshold = capacity * load_factor<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> load_factor Ϊ table <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>ʹ<EFBFBD>õı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>load_factor <20><><EFBFBD><EFBFBD><EFBFBD>ᵼ<EFBFBD>¾۴صij<D8B5><C4B3>֣<EFBFBD><D6A3>Ӷ<EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD>ѯ<EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>ʼǡ<CABC>
|
||||
threshold = capacity * load_factor,其中 load_factor 为 table 数组能够使用的比例,load_factor 过大会导致聚簇的出现,从而影响查询和插入的效率,详见算法笔记。
|
||||
|
||||
```java
|
||||
static final int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
@ -268,7 +269,7 @@ final float loadFactor;
|
||||
transient int modCount;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ش<EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> capacity Ϊԭ<CEAA><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
从下面的添加元素代码中可以看出,当需要扩容时,令 capacity 为原来的两倍。
|
||||
|
||||
```java
|
||||
void addEntry(int hash, K key, V value, int bucketIndex) {
|
||||
@ -279,7 +280,7 @@ void addEntry(int hash, K key, V value, int bucketIndex) {
|
||||
}
|
||||
```
|
||||
|
||||
Entry <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>Ԫ<EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> next ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ʱ<EFBFBD><CAB1>ʹ<EFBFBD>á<EFBFBD>
|
||||
Entry 用来表示一个键值对元素,其中的 next 指针在序列化时会使用。
|
||||
|
||||
```java
|
||||
static class Entry<K,V> implements Map.Entry<K,V> {
|
||||
@ -290,7 +291,7 @@ static class Entry<K,V> implements Map.Entry<K,V> {
|
||||
}
|
||||
```
|
||||
|
||||
get() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>key Ϊ null <EFBFBD><EFBFBD> <20><>Ϊ null<6C><6C><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF>Կ<EFBFBD><D4BF><EFBFBD> HashMap <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> null <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
|
||||
get() 操作需要分成两种情况,key 为 null 和 不为 null,从中可以看出 HashMap 允许插入 null 作为键。
|
||||
|
||||
```java
|
||||
public V get(Object key) {
|
||||
@ -306,7 +307,7 @@ public V get(Object key) {
|
||||
}
|
||||
```
|
||||
|
||||
put() <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> key <EFBFBD>Ƿ<EFBFBD>Ϊ null <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD> key Ϊ null <EFBFBD>ļ<EFBFBD>ֵ<EFBFBD>ԣ<EFBFBD><EFBFBD>²<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> key Ϊ null <EFBFBD>ļ<EFBFBD>ֵ<EFBFBD><EFBFBD>ʱĬ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 λ<>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ null <20><><EFBFBD>ܼ<EFBFBD><DCBC><EFBFBD> hash ֵ<><D6B5>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>֪<EFBFBD><D6AA>Ӧ<EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
put() 操作也需要根据 key 是否为 null 做不同的处理,需要注意的是如果本来没有 key 为 null 的键值对,新插入一个 key 为 null 的键值对时默认是放在数组的 0 位置,这是因为 null 不能计算 hash 值,也就无法知道应该放在哪个链表上。
|
||||
|
||||
```java
|
||||
public V put(K key, V value) {
|
||||
@ -354,8 +355,8 @@ private V putForNullKey(V value) {
|
||||
|
||||
[ConcurrentHashMap.java](https://github.com/CyC2018/InterviewNotes/blob/master/notes/src/HashMap.java)
|
||||
|
||||
[ ̽<EFBFBD><EFBFBD> ConcurrentHashMap <EFBFBD>߲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD>ʵ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD> ](https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/)
|
||||
[ 探索 ConcurrentHashMap 高并发性的实现机制 ](https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/)
|
||||
|
||||
# <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 参考资料
|
||||
|
||||
- Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD>
|
||||
- Java 编程思想
|
||||
|
1241
notes/Leetcode 题解.md
1241
notes/Leetcode 题解.md
File diff suppressed because it is too large
Load Diff
851
notes/Linux.md
851
notes/Linux.md
File diff suppressed because it is too large
Load Diff
407
notes/MySQL.md
407
notes/MySQL.md
@ -1,226 +1,227 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD>)
|
||||
* [存储引擎](#存储引擎)
|
||||
* [1. InnoDB](#1-innodb)
|
||||
* [2. MyISAM](#2-myisam)
|
||||
* [3. InnoDB <EFBFBD><EFBFBD> MyISAM <EFBFBD>ıȽ<EFBFBD>](#3-innodb-<EFBFBD><EFBFBD>-myisam-<EFBFBD>ıȽ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#2-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>](#3-<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4. ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#4-ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.1 B-Tree <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#11-b-tree-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.2 <EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#12-<EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1.3. <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>R-Tree<EFBFBD><EFBFBD>](#13-<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>r-tree)
|
||||
* [1.4 ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#14-ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD>](#2-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>)
|
||||
* [3.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#31-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.2 ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#32-ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#33-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>˳<EFBFBD><EFBFBD>](#34-<2D><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>˳<EFBFBD><CBB3>)
|
||||
* [3.5 <EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#35-<EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.6 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#36-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4. B-Tree <EFBFBD><EFBFBD> B+Tree ԭ<EFBFBD><EFBFBD>](#4-b-tree-<EFBFBD><EFBFBD>-b+tree-ԭ<EFBFBD><EFBFBD>)
|
||||
* [3. InnoDB 与 MyISAM 的比较](#3-innodb-与-myisam-的比较)
|
||||
* [数据类型](#数据类型)
|
||||
* [1. 整型](#1-整型)
|
||||
* [2. 浮点数](#2-浮点数)
|
||||
* [3. 字符串](#3-字符串)
|
||||
* [4. 时间和日期](#4-时间和日期)
|
||||
* [索引](#索引)
|
||||
* [1. 索引分类](#1-索引分类)
|
||||
* [1.1 B-Tree 索引](#11-b-tree-索引)
|
||||
* [1.2 哈希索引](#12-哈希索引)
|
||||
* [1.3. 空间索引数据(R-Tree)](#13-空间索引数据r-tree)
|
||||
* [1.4 全文索引](#14-全文索引)
|
||||
* [2. 索引的优点](#2-索引的优点)
|
||||
* [3. 索引优化](#3-索引优化)
|
||||
* [3.1 独立的列](#31-独立的列)
|
||||
* [3.2 前缀索引](#32-前缀索引)
|
||||
* [3.3 多列索引](#33-多列索引)
|
||||
* [3.4 索引列的顺序](#34-索引列的顺序)
|
||||
* [3.5 聚簇索引](#35-聚簇索引)
|
||||
* [3.6 覆盖索引](#36-覆盖索引)
|
||||
* [4. B-Tree 和 B+Tree 原理](#4-b-tree-和-b+tree-原理)
|
||||
* [4. 1 B-Tree](#4-1-b-tree)
|
||||
* [4.2 B+Tree](#42-b+tree)
|
||||
* [4.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> B+Tree](#43-<2D><><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>-b+tree)
|
||||
* [4.4 Ϊʲôʹ<EFBFBD><EFBFBD> B-Tree <EFBFBD><EFBFBD> B+Tree](#44-Ϊʲôʹ<EFBFBD><EFBFBD>-b-tree-<EFBFBD><EFBFBD>-b+tree)
|
||||
* [<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>](#<23><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>)
|
||||
* [4.3 带有顺序访问指针的 B+Tree](#43-带有顺序访问指针的-b+tree)
|
||||
* [4.4 为什么使用 B-Tree 和 B+Tree](#44-为什么使用-b-tree-和-b+tree)
|
||||
* [查询性能优化](#查询性能优化)
|
||||
* [1. Explain](#1-explain)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>](#2-<2D><><EFBFBD>ٷ<EFBFBD><D9B7>ص<EFBFBD><D8B5><EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>](#3-<2D><><EFBFBD>ٷ<EFBFBD><D9B7>ص<EFBFBD><D8B5><EFBFBD>)
|
||||
* [4. <EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD> DELETE <EFBFBD><EFBFBD> INSERT <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#4-<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD>-delete-<EFBFBD><EFBFBD>-insert-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>](#<23>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD>ֱ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ƺ<EFBFBD><EFBFBD>ϻָ<EFBFBD>](#<23><><EFBFBD><EFBFBD>ת<EFBFBD>ƺ<C6BA><CDB9>ϻָ<CFBB>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD>ϻָ<EFBFBD>](#2-<EFBFBD><EFBFBD><EFBFBD>ϻָ<EFBFBD>)
|
||||
* [<EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. 减少返回的列](#2-减少返回的列)
|
||||
* [3. 减少返回的行](#3-减少返回的行)
|
||||
* [4. 拆分大的 DELETE 或 INSERT 语句](#4-拆分大的-delete-或-insert-语句)
|
||||
* [分库与分表](#分库与分表)
|
||||
* [故障转移和故障恢复](#故障转移和故障恢复)
|
||||
* [1. 故障转移](#1-故障转移)
|
||||
* [2. 故障恢复](#2-故障恢复)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD>
|
||||
|
||||
# 存储引擎
|
||||
|
||||
## 1. InnoDB
|
||||
|
||||
InnoDB <EFBFBD><EFBFBD> MySQL <EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ InnoDB <20><>֧<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ſ<EFBFBD><C5BF><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2><EFBFBD>档
|
||||
InnoDB 是 MySQL 的默认事务型引擎,只有在需要 InnoDB 不支持的特性时,才考虑使用其它存储引擎。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> MVCC <EFBFBD><EFBFBD>֧<EFBFBD>ָ߲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>뼶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
采用 MVCC 来支持高并发,并且实现了四个标准的隔离级别,默认级别是可重复读。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>ھ۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܸߵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
表是基于聚簇索引建立的,它对主键的查询性能有很高的提升。
|
||||
|
||||
<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˺ܶ<EFBFBD><EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD><EFBFBD>̶<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>õĿ<EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD> hash <20><><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD>ٲ<EFBFBD><D9B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2>뻺<EFBFBD><EBBBBA><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
内部做了很多优化,包括从磁盘读取数据时采用的可预测性读,能够自动在内存中创建 hash 索引以加速读操作的自适应哈希索引,以及能够加速插入操作的插入缓冲区等。
|
||||
|
||||
ͨ<EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD>ƺ<EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
通过一些机制和工具支持真正的热备份。
|
||||
|
||||
## 2. MyISAM
|
||||
|
||||
MyISAM <EFBFBD>ṩ<EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ亯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>GIS<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD> MyISAM <20><>֧<EFBFBD><D6A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD><D2B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD>ȫ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>
|
||||
MyISAM 提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等。但 MyISAM 不支持事务和行级锁,而且奔溃后无法安全恢复。
|
||||
|
||||
ֻ<EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ű<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
只能对整张表加锁,而不是针对行。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ִ<EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿdz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
可以手工或者自动执行检查和修复操作,但是和事务恢复以及奔溃恢复不同,可能导致一些数据丢失,而且修复操作是非常慢的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>߾<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
可以包含动态或者静态的行。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> DELAY_KEY_WRITE ѡ<EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>еļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߹رձ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ŻὫ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
如果指定了 DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立即将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘。这种方式可以极大的提升写入性能,但是在数据库或者主机奔溃时会造成索引损坏,需要执行修复操作。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ʺϲ<EFBFBD><EFBFBD><EFBFBD> MyISAM ѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
如果表在创建并导入数据以后,不会再进行修改操作,那么这样的表适合采用 MyISAM 压缩表。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD>Ƚ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> MyISAM<EFBFBD><EFBFBD>
|
||||
对于只读数据,或者表比较小、可以容忍修复操作,则依然可以继续使用 MyISAM。
|
||||
|
||||
MyISAM <EFBFBD><EFBFBD><EFBFBD>Ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>ܸ<EFBFBD>ʽ<EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ijЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܺܺá<EFBFBD>
|
||||
MyISAM 设计简单,数据以紧密格式存储,所以在某些场景下性能很好。
|
||||
|
||||
## 3. InnoDB <EFBFBD><EFBFBD> MyISAM <EFBFBD>ıȽ<EFBFBD>
|
||||
## 3. InnoDB 与 MyISAM 的比较
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**事务**
|
||||
|
||||
InnoDB <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵ġ<EFBFBD>
|
||||
InnoDB 是事务型的。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**备份**
|
||||
|
||||
InnoDB ֧<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
InnoDB 支持在线热备份。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>**
|
||||
**奔溃恢复**
|
||||
|
||||
MyISAM <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>ʱ<EFBFBD> InnoDB <20>ߺܶ࣬<DCB6><E0A3AC><EFBFBD>һָ<D2BB><D6B8><EFBFBD><EFBFBD>ٶ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
MyISAM 奔溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**并发**
|
||||
|
||||
MyISAM ֻ֧<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> InnoDB <20><>֧<EFBFBD><D6A7><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD>
|
||||
MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**其它特性**
|
||||
|
||||
MyISAM ֧<EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
MyISAM 支持全文索引,地理空间索引;
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 数据类型
|
||||
|
||||
## 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 1. 整型
|
||||
|
||||
TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT <EFBFBD>ֱ<EFBFBD>ʹ<EFBFBD><EFBFBD> 8, 16, 24, 64 λ<EFBFBD>洢<EFBFBD>ռ䣬һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԽС<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD>á<EFBFBD>
|
||||
TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT 分别使用 8, 16, 24, 64 位存储空间,一般情况下越小的列越好。
|
||||
|
||||
INT(11) <EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ǹ涨<EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>ַ<EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
INT(11) 中的数字只是规定了交互工具显示字符的个数,对于存储和计算来说是没有意义的。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 2. 浮点数
|
||||
|
||||
FLOAT <EFBFBD><EFBFBD> DOUBLE Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>DECIMAL Ϊ<>߾<EFBFBD><DFBE><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>CPU ԭ<><D4AD>֧<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD>Dz<EFBFBD>֧<EFBFBD><D6A7> DECIMAl <20><><EFBFBD>͵ļ<CDB5><C4BC>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD> DECIMAL <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>ȸ<EFBFBD><C8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ߵĴ<DFB5><C4B4>ۡ<EFBFBD>
|
||||
FLOAT 和 DOUBLE 为浮点类型,DECIMAL 为高精度小数类型。CPU 原生支持浮点运算,但是不支持 DECIMAl 类型的计算,因此 DECIMAL 的计算比浮点类型需要更高的代价。
|
||||
|
||||
FLOAT<EFBFBD><EFBFBD>DOUBLE <EFBFBD><EFBFBD> DECIMAL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DECIMAL(18, 9) <20><>ʾ<EFBFBD>ܹ<EFBFBD> 18 λ<><CEBB>ȡ 9 λ<>洢С<E6B4A2><D0A1><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>ʣ<EFBFBD><CAA3> 9 λ<>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>
|
||||
FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示总共 18 位,取 9 位存储小数部分,剩下 9 位存储整数部分。
|
||||
|
||||
## 3. <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 字符串
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> CHAR <EFBFBD><EFBFBD> VARCHAR <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>DZ䳤<EFBFBD>ġ<EFBFBD>
|
||||
主要有 CHAR 和 VARCHAR 两种类型,一种是定长的,一种是变长的。
|
||||
|
||||
VARCHAR <EFBFBD><EFBFBD><EFBFBD>ֱ䳤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD>ʡ<EFBFBD>ռ䣬<EFBFBD><EFBFBD>Ϊֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD>洢<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> UPDATE ʱ<><CAB1><EFBFBD>ܻ<EFBFBD>ʹ<EFBFBD>б<EFBFBD><D0B1>ñ<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵĴ<C9B5>Сʱ<D0A1><CAB1><EFBFBD><EFBFBD>Ҫִ<D2AA>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>MyISAM <20>Ὣ<EFBFBD>в<EFBFBD><D0B2>ɲ<EFBFBD>ͬ<EFBFBD><CDAC>Ƭ<EFBFBD>δ洢<CEB4><E6B4A2><EFBFBD><EFBFBD> InnoDB <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>ʹ<EFBFBD>зŽ<D0B7>ҳ<EFBFBD>ڡ<EFBFBD>
|
||||
VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作,MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。
|
||||
|
||||
VARCHAR <EFBFBD>ᱣ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ĩβ<EFBFBD>Ŀո<EFBFBD> CHAR <20><>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>
|
||||
VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。
|
||||
|
||||
## 4. ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4. 时间和日期
|
||||
|
||||
MySQL <EFBFBD>ṩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>DATATIME <EFBFBD><EFBFBD> TIMESTAMP<EFBFBD><EFBFBD>
|
||||
MySQL 提供了两种相似的日期时间类型:DATATIME 和 TIMESTAMP。
|
||||
|
||||
**DATATIME**
|
||||
|
||||
<EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1001 <EFBFBD>굽 9999 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>룬ʹ<EFBFBD><EFBFBD> 8 <20>ֽڵĴ洢<C4B4>ռ䡣
|
||||
能够保存从 1001 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ء<EFBFBD>
|
||||
它与时区无关。
|
||||
|
||||
Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>MySQL <20><>һ<EFBFBD>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ʽ<EFBFBD><CABD>ʾ DATATIME ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>硰2008-01016 22:37:08<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ANSI <20><><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATATIME 值,例如“2008-01016 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。
|
||||
|
||||
**TIMESTAMP**
|
||||
|
||||
<EFBFBD><EFBFBD> UNIX ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1970 <EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䣩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> 4 <20><><EFBFBD>ֽڣ<D6BD>ֻ<EFBFBD>ܱ<EFBFBD>ʾ<EFBFBD><CABE> 1970 <EFBFBD><EFBFBD> <20><> 2038 <EFBFBD>ꡣ
|
||||
和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>йء<EFBFBD>
|
||||
它和时区有关。
|
||||
|
||||
MySQL <EFBFBD>ṩ<EFBFBD><EFBFBD> FROM_UNIXTIME() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Unxi ʱ<><CAB1><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD>ṩ<EFBFBD><E1B9A9> UNIX_TIMESTAMP() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ Unix ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
MySQL 提供了 FROM_UNIXTIME() 函数把 Unxi 时间戳转换为日期,并提供了 UNIX_TIMESTAMP() 函数把日期转换为 Unix 时间戳。
|
||||
|
||||
Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱû<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> TIMESTAMP <20>е<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>Ὣ<EFBFBD><E1BDAB><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰʱ<C7B0>䡣
|
||||
默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。
|
||||
|
||||
Ӧ<EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> TIMESTAMP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> DATETIME <EFBFBD>ռ<EFBFBD>Ч<EFBFBD>ʸ<EFBFBD><EFBFBD>ߡ<EFBFBD>
|
||||
应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 索引
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>ͬ<EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͺ<EFBFBD>ʵ<EFBFBD>֡<EFBFBD>
|
||||
索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
索引能够轻易将查询性能提升几个数量级。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڷdz<EFBFBD>С<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>ȫ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷdz<EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD><EFBFBD>͵ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>۽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>õ<EFBFBD>һ<EFBFBD>ּ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD>ƥ<EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和使用索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。
|
||||
|
||||
## 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 1. 索引分类
|
||||
|
||||
### 1.1 B-Tree <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.1 B-Tree 索引
|
||||
|
||||
B-Tree <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> MySQL <20>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
B-Tree 索引是大多数 MySQL 存储引擎的默认索引类型。
|
||||
|
||||
<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ɨ<EFBFBD>裬ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȿ<EFBFBD><EFBFBD>ܶࡣ
|
||||
因为不再需要进行全表扫描,只需要对树进行搜索即可,因此查找速度快很多。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD>B-Tree <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>Χ<EFBFBD>ͼ<EFBFBD>ǰ<C7B0><D7BA><EFBFBD>ң<EFBFBD><D2A3><EFBFBD><EFBFBD>м<EFBFBD>ǰ<C7B0><D7BA><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<C7B0><D7BA><EFBFBD>ҡ<EFBFBD>
|
||||
可以指定多个列作为索引列,多个索引列共同组成键。B-Tree 索引适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>顣
|
||||
除了用于查找,还可以用于排序和分组。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
如果不是按照索引列的顺序进行查找,则无法使用索引。
|
||||
|
||||
### 1.2 <EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.2 哈希索引
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD>ϣ<EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD>ҷdz<EFBFBD><EFBFBD>졣
|
||||
基于哈希表实现,优点是查找非常快。
|
||||
|
||||
<EFBFBD><EFBFBD> MySQL <EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD> Memory <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ֧<EFBFBD>ֹ<EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在 MySQL 中只有 Memory 引擎显式支持哈希索引。
|
||||
|
||||
InnoDB <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>ܽС<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ʹ<EFBFBD>õķdz<EFBFBD>Ƶ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B-Tree <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>ٴ<EFBFBD><D9B4><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B-Tree <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<D2BB>ŵ㣬<C5B5><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٵĹ<D9B5>ϣ<EFBFBD><CFA3><EFBFBD>ҡ<EFBFBD>
|
||||
InnoDB 引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B-Tree 索引之上再创建一个哈希索引,这样就让 B-Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD>ֶ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>ٶȺܿ죬<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD>첢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ֧<EFBFBD>־<EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>Һͷ<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD>ͻ<EFBFBD>ܶ࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶȻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ú<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
限制:哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能影响并不明显;无法用于分组与排序;只支持精确查找,无法用于部分查找和范围查找;如果哈希冲突很多,查找速度会变得很慢。
|
||||
|
||||
### 1.3. <EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>R-Tree<EFBFBD><EFBFBD>
|
||||
### 1.3. 空间索引数据(R-Tree)
|
||||
|
||||
MyISAM <EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD>ֿռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ洢<EFBFBD><EFBFBD>
|
||||
MyISAM 存储引擎支持空间索引,可以用于地理数据存储。
|
||||
|
||||
<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>ѯ<EFBFBD><EFBFBD>
|
||||
空间索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。
|
||||
|
||||
### 1.4 ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1.4 全文索引
|
||||
|
||||
MyISAM <EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>еĹؼ<EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӱȽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><EFBFBD>
|
||||
MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较索引中的值。
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> MATCH AGAINST<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> WHERE<EFBFBD><EFBFBD>
|
||||
使用 MATCH AGAINST,而不是普通的 WHERE。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD>
|
||||
## 2. 索引的优点
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 大大减少了服务器需要扫描的数据量;
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 帮助服务器避免进行排序和创建临时表;
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20><>Ϊ˳<CEAA><CBB3> I/O<EFBFBD><EFBFBD>
|
||||
- 将随机 I/O 变为顺序 I/O。
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>
|
||||
## 3. 索引优化
|
||||
|
||||
### 3.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.1 独立的列
|
||||
|
||||
<EFBFBD>ڽ<EFBFBD><EFBFBD>в<EFBFBD>ѯʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法使用索引。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> actor_id <EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
例如下面的查询不能使用 actor_id 列的索引:
|
||||
|
||||
```sql
|
||||
SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;
|
||||
```
|
||||
|
||||
### 3.2 ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.2 前缀索引
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> BLOB<EFBFBD><EFBFBD>TEXT <EFBFBD><EFBFBD> VARCHAR <EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
对于 BLOB、TEXT 和 VARCHAR 类型的列,必须使用前缀索引,只索引开始的部分字符。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD>ѡȡ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20><>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ͼ<EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>ֵ<EFBFBD><D6B5>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Խ<EFBFBD>ߣ<EFBFBD><DFA3><EFBFBD>ѯЧ<D1AF><D0A7>ҲԽ<D2B2>ߡ<EFBFBD><DFA1><EFBFBD><EFBFBD><EFBFBD>ֵΪ 1 <20><><EFBFBD><EFBFBD>ʱÿ<CAB1><C3BF><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD>Ψһ<CEA8><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>
|
||||
对于前缀长度的选取需要根据 **索引选择性** 来确定:不重复的索引值和记录总数的比值。选择性越高,查询效率也越高。最大值为 1 ,此时每个记录都有唯一的索引与其对应。
|
||||
|
||||
### 3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.3 多列索引
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD>ѯʱ<EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܸ<EFBFBD><EFBFBD>á<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD> actor_id <EFBFBD><EFBFBD> file_id <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在需要使用多个列作为条件进行查询时,使用多列索引比使用多个单列索引性能更好。例如下面的语句中,最好把 actor_id 和 file_id 设置为多列索引。
|
||||
|
||||
```sql
|
||||
SELECT file_id, actor_ id FROM sakila.film_actor
|
||||
WhERE actor_id = 1 OR film_id = 1;
|
||||
```
|
||||
|
||||
### 3.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>˳<EFBFBD><EFBFBD>
|
||||
### 3.4 索引列的顺序
|
||||
|
||||
<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> customer_id <EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD> staff_id <EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD> customer_id <20>з<EFBFBD><D0B7>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>档
|
||||
让选择性最强的索引列放在前面,例如下面显示的结果中 customer_id 的选择性比 staff_id 更高,因此最好把 customer_id 列放在多列索引的前面。
|
||||
|
||||
```sql
|
||||
SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
|
||||
@ -235,107 +236,107 @@ customer_id_selectivity: 0.0373
|
||||
COUNT(*): 16049
|
||||
```
|
||||
|
||||
### 3.5 <EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.5 聚簇索引
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ洢<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
聚簇索引并不是一种索引类型,而是一种数据存储方式。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۴ء<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>к<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵļ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>ܵش洢<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>InnoDB <20>ľ۴<C4BE><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD> B-Tree <20><>Ҷ<EFBFBD><D2B6>ҳ<EFBFBD>С<EFBFBD>
|
||||
术语“聚簇”表示数据行和相邻的键值紧密地存储在一起,InnoDB 的聚簇索引的数据行存放在 B-Tree 的叶子页中。
|
||||
|
||||
<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ĵط<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
|
||||
|
||||
**<EFBFBD>ŵ<EFBFBD>**
|
||||
**优点**
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>𣬼<EFBFBD><EFBFBD><EFBFBD> I/O <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B-Tree <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7>ʸ<EFBFBD><CAB8>졣
|
||||
1. 可以把相关数据保存在一起,减少 I/O 操作;
|
||||
2. 因为数据保存在 B-Tree 中,因此数据访问更快。
|
||||
|
||||
**ȱ<EFBFBD><EFBFBD>**
|
||||
**缺点**
|
||||
|
||||
1. <EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20>ܼ<EFBFBD><DCBC><EFBFBD>Ӧ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<DAB4><E6A3AC>û<EFBFBD><C3BB>Ҫ<EFBFBD>þ۴<C3BE><DBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۺܸߣ<EFBFBD><EFBFBD><EFBFBD>Ϊÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>λ<EFBFBD>á<EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD>У<EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ὣ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ѳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸ<EFBFBD><EFBFBD>У<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ѻᵼ<EFBFBD>±<EFBFBD>ռ<EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>̿ռ䡣
|
||||
5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>бȽ<EFBFBD>ϡ<EFBFBD>裬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>۴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>ٶȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1. 聚簇索引最大限度提高了 I/O 密集型应用的性能,但是如果数据全部放在内存,就没必要用聚簇索引。
|
||||
2. 插入速度严重依赖于插入顺序,按主键的顺序插入是最快的。
|
||||
3. 更新操作代价很高,因为每个被更新的行都会移动到新的位置。
|
||||
4. 当插入到某个已满的页中,存储引擎会将该页分裂成两个页面来容纳该行,页分裂会导致表占用更多的磁盘空间。
|
||||
5. 如果行比较稀疏,或者由于页分裂导致数据存储不连续时,聚簇索引可能导致全表扫描速度变慢。
|
||||
|
||||
### 3.6 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3.6 覆盖索引
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>ֶε<EFBFBD>ֵ<EFBFBD><EFBFBD>
|
||||
索引包含所有需要查询的字段的值。
|
||||
|
||||
## 4. B-Tree <EFBFBD><EFBFBD> B+Tree ԭ<EFBFBD><EFBFBD>
|
||||
## 4. B-Tree 和 B+Tree 原理
|
||||
|
||||
### 4. 1 B-Tree
|
||||
|
||||

|
||||

|
||||
|
||||
Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B-Tree<65><65><EFBFBD><EFBFBD><EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>¼Ϊһ<CEAA><D2BB><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA> [key, data]<EFBFBD><EFBFBD>key Ϊ<EFBFBD><EFBFBD>¼<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>data Ϊ<><CEAA><EFBFBD>ݼ<EFBFBD>¼<EFBFBD><C2BC> key <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
为了描述 B-Tree,首先定义一条数据记录为一个二元组 [key, data],key 为记录的键,data 为数据记录除 key 外的数据。
|
||||
|
||||
B-Tree <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽṹ<EFBFBD><EFBFBD>
|
||||
B-Tree 是满足下列条件的数据结构:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵ B-Tree <20><>ƽ<EFBFBD><C6BD><EFBFBD>ģ<EFBFBD>
|
||||
- һ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD>е<EFBFBD> key <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҷǵݼ<C7B5><DDBC><EFBFBD><EFBFBD>У<EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> key <20>ֱ<EFBFBD><D6B1><EFBFBD> key<sub>i</sub> <EFBFBD><EFBFBD> key<sub>i+1</sub><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD>Ϊ null<6C><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ָ<EFBFBD><D6B8><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> key <EFBFBD><EFBFBD><EFBFBD><EFBFBD> key<sub>i</sub> <EFBFBD><EFBFBD>С<EFBFBD><EFBFBD> key<sub>i+1</sub><EFBFBD><EFBFBD>
|
||||
- 所有叶节点具有相同的深度,也就是说 B-Tree 是平衡的;
|
||||
- 一个节点中的 key 从左到右非递减排列;
|
||||
- 如果某个指针的左右相邻 key 分别是 key<sub>i</sub> 和 key<sub>i+1</sub>,且不为 null,则该指针指向节点的所有 key 大于 key<sub>i</sub> 且小于 key<sub>i+1</sub>。
|
||||
|
||||
<EFBFBD><EFBFBD> B-Tree <EFBFBD>а<EFBFBD> key <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD>㷨<EFBFBD>dz<EFBFBD>ֱ<EFBFBD>ۣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴӸ<EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>ض<EFBFBD>Ӧ<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> data<74><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ָ<EFBFBD><D6B8><EFBFBD>Ľڵ<C4BD><DAB5>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD>в<EFBFBD><D0B2>ң<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ҵ<EFBFBD><D2B5>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ҵ<EFBFBD> null ָ<>룬ǰ<EBA3AC>߲<EFBFBD><DFB2>ҳɹ<D2B3><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2><EFBFBD>ʧ<EFBFBD>ܡ<EFBFBD>
|
||||
在 B-Tree 中按 key 检索数据的算法非常直观:首先从根节点进行二分查找,如果找到则返回对应节点的 data,否则对相应区间的指针指向的节点递归进行查找,直到找到节点或找到 null 指针,前者查找成功,后者查找失败。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD> B-Tree <20><><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD>ɾ<EFBFBD><C9BE>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>ϲ<EFBFBD><CFB2><EFBFBD>ת<EFBFBD>ƵȲ<C6B5><C8B2><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD> B-Tree <EFBFBD><EFBFBD><EFBFBD>ʡ<EFBFBD>
|
||||
由于插入删除新的数据记录会破坏 B-Tree 的性质,因此在插入删除时,需要对树进行一个分裂、合并、转移等操作以保持 B-Tree 性质。
|
||||
|
||||
### 4.2 B+Tree
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD> B-Tree <EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>B+Tree <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD>ͬ<EFBFBD>㣺
|
||||
与 B-Tree 相比,B+Tree 有以下不同点:
|
||||
|
||||
- ÿ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 2d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2d+1<EFBFBD><EFBFBD>
|
||||
- <EFBFBD>ڽڵ㲻<EFBFBD>洢 data<74><61>ֻ<EFBFBD>洢 key<65><79>Ҷ<EFBFBD>ӽڵ㲻<DAB5>洢ָ<E6B4A2>롣
|
||||
- 每个节点的指针上限为 2d 而不是 2d+1;
|
||||
- 内节点不存储 data,只存储 key,叶子节点不存储指针。
|
||||
|
||||
### 4.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> B+Tree
|
||||
### 4.3 带有顺序访问指针的 B+Tree
|
||||
|
||||

|
||||

|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ϵͳ<EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD> B+Tree <20>ṹ<EFBFBD><E1B9B9><EFBFBD>ھ<EFBFBD><DABE><EFBFBD> B+Tree <20><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ӽڵ<D3BD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 基础上进行了优化,在叶子节点增加了顺序访问指针,做这个优化的目的是为了提高区间访问的性能。
|
||||
|
||||
### 4.4 Ϊʲôʹ<EFBFBD><EFBFBD> B-Tree <EFBFBD><EFBFBD> B+Tree
|
||||
### 4.4 为什么使用 B-Tree 和 B+Tree
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽṹҲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD>ϵͳ<EFBFBD>ձ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B-/+Tree <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ṹ<EFBFBD><E1B9B9>
|
||||
红黑树等数据结构也可以用来实现索引,但是文件系统及数据库系统普遍采用 B-/+Tree 作为索引结构。
|
||||
|
||||
ҳ<EFBFBD>Ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>̴洢<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ȵĿ飬ÿ<EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>У<EFBFBD>ҳ<EFBFBD>ô<EFBFBD>Сͨ<EFBFBD><EFBFBD>Ϊ 4k<34><6B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CDB4><EFBFBD><EFBFBD><EFBFBD>ҳΪ<D2B3><CEAA>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(在许多操作系统中,页得大小通常为 4k),主存和磁盘以页为单位交换数据。
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD>ܴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>洢<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>Ϊ<EFBFBD>˼<EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD> I/O<><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD>ζ<EFBFBD><CEB6><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǽ<EFBFBD><C7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľֲ<C4BE><D6B2><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><DDB1>õ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>丽<EFBFBD><E4B8BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳͨ<D2B2><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>ʹ<EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD>ݿ<EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><CBB4><EFBFBD>Ԥ<EFBFBD><D4A4>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ڵ<EFBFBD><DAB5>Ĵ<EFBFBD>С<EFBFBD><D0A1>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ڵ<EFBFBD>ֻ<EFBFBD><D6BB>Ҫһ<D2AA><D2BB> I/O <20>Ϳ<EFBFBD><CDBF><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>롣B-Tree <20><>һ<EFBFBD>μ<EFBFBD><CEBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ h-1 <EFBFBD><EFBFBD> I/O<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㳣פ<EFBFBD>ڴ棩<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>Ϊ O(h)=O(logdN)<29><>һ<EFBFBD><D2BB>ʵ<EFBFBD><CAB5>Ӧ<EFBFBD><D3A6><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD> d <20>Ƿdz<C7B7><C7B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 100<30><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD> h <20>dz<EFBFBD>С<EFBFBD><D0A1>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽṹ<D6BD><E1B9B9>h <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>Ķࡣ<C4B6><E0A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBC>Ϻܽ<CFBA><DCBD>Ľڵ㣨<DAB5><E3A3A8><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF>ܺ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD>þֲ<C3BE><D6B2>ԣ<EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD> B-Tree <EFBFBD><EFBFBD><EFBFBD>ܶࡣ
|
||||
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次 I/O 就可以完全载入。B-Tree 中一次检索最多需要 h-1 次 I/O(根节点常驻内存),渐进复杂度为 O(h)=O(logdN)。一般实际应用中,出度 d 是非常大的数字,通常超过 100,因此 h 非常小(通常不超过 3)。而红黑树这种结构,h 明显要深的多。并且于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性,效率明显比 B-Tree 差很多。
|
||||
|
||||
B+Tree <EFBFBD><EFBFBD><EFBFBD>ʺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> d <20>йء<D0B9><D8A1><EFBFBD><EFBFBD><EFBFBD> B+Tree <20>ڽڵ<DABD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD> data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD><CBBF><EFBFBD>ӵ<EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD>ij<EFBFBD><C4B3>ȣ<EFBFBD>ӵ<EFBFBD>и<EFBFBD><D0B8>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
B+Tree 更适合外存索引,原因和内节点出度 d 有关。由于 B+Tree 内节点去掉了 data 域,因此可以拥有更大的出度,拥有更好的性能。
|
||||
|
||||
# <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>
|
||||
# 查询性能优化
|
||||
|
||||
## 1. Explain
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SQL <20><><EFBFBD>䣬<EFBFBD><E4A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>бȽ<D0B1><C8BD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ֶ<EFBFBD><D6B6>У<EFBFBD>
|
||||
用来分析 SQL 语句,分析结果中比较重要的字段有:
|
||||
|
||||
- select_type : <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>м<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD>ѯ
|
||||
- select_type : 查询类型,有简单查询、联合查询和子查询
|
||||
|
||||
- key : ʹ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- key : 使用的索引
|
||||
|
||||
- rows : ɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- rows : 扫描的行数
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 2. 减少返回的列
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>⣬Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
慢查询主要是因为访问了过多数据,除了访问过多行之外,也包括访问过多列。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>Ҫʹ<EFBFBD><EFBFBD> SELECT * <EFBFBD><EFBFBD><EFBFBD>䣬Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
最好不要使用 SELECT * 语句,要根据需要选择查询的列。
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD>
|
||||
## 3. 减少返回的行
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> LIMIT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>Щ<EFBFBD>С<EFBFBD>
|
||||
最好使用 LIMIT 语句来取出想要的那些行。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ɨ<EFBFBD>衣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD>ɨ<EFBFBD>裬<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫɨ<EFBFBD>輸<EFBFBD>м<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>ʹ<EFBFBD><EFBFBD> Explain <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>۲<EFBFBD> rows <20>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2>졣
|
||||
还可以建立索引来减少条件语句的全表扫描。例如对于下面的语句,不适用索引的情况下需要进行全表扫描,而使用索引只需要扫描几行记录即可,使用 Explain 语句可以通过观察 rows 字段来看出这种差异。
|
||||
|
||||
```sql
|
||||
SELECT * FROM sakila.film_actor WHERE film_id = 1;
|
||||
```
|
||||
|
||||
## 4. <EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD> DELETE <EFBFBD><EFBFBD> INSERT <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4. 拆分大的 DELETE 或 INSERT 语句
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>еĻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ס<EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>ϵͳ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD>С<EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>IJ<EFBFBD>ѯ<EFBFBD><EFBFBD>
|
||||
如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。
|
||||
|
||||
```sql
|
||||
DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH);
|
||||
@ -348,74 +349,74 @@ do {
|
||||
} while rows_affected > 0
|
||||
```
|
||||
|
||||
# <EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>
|
||||
# 分库与分表
|
||||
|
||||
**1. <EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ͬ**
|
||||
**1. 分表与分区的不同**
|
||||
|
||||
<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD>һ<EFBFBD>ű<EFBFBD><EFBFBD>ֳɶ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ЩС<EFBFBD><EFBFBD>ӵ<EFBFBD>в<EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD>һ<EFBFBD>ű<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ洢<EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>Դ洢<EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽ<EFBFBD>±<EFBFBD><EFBFBD><EFBFBD>Ȼֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
分表,就是讲一张表分成多个小表,这些小表拥有不同的表名;而分区是将一张表的数据分为多个区块,这些区块可以存储在同一个磁盘上,也可以存储在不同的磁盘上,这种方式下表仍然只有一个。
|
||||
|
||||
**2. ʹ<EFBFBD>÷ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**2. 使用分库与分表的原因**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>еı<EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>Խ<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
随着时间和业务的发展,数据库中的表会越来越多,并且表中的数据量也会越来越大,那么读写操作的开销也会随着增大。
|
||||
|
||||
**3. <EFBFBD><EFBFBD>ֱ<EFBFBD>з<EFBFBD>**
|
||||
**3. 垂直切分**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>顢<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD>г̶Ȼ<EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ϡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>磬<EFBFBD><EFBFBD><EFBFBD>ǻὨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD> payDB<44><42><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>ݿ<EFBFBD> userDB <20>ȣ<EFBFBD><C8A3>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>Ʒ<EFBFBD>йصı<D8B5><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>йصı<D8B5><C4B1><EFBFBD>
|
||||
将表按功能模块、关系密切程度划分出来,部署到不同的库上。例如,我们会建立商品数据库 payDB、用户数据库 userDB 等,分别用来存储项目与商品有关的表和与用户有关的表。
|
||||
|
||||
**4. ˮƽ<EFBFBD>з<EFBFBD>**
|
||||
**4. 水平切分**
|
||||
|
||||
<EFBFBD>ѱ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṹ<EFBFBD><EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>簴 id <20><>ɢ<EFBFBD><C9A2>ֵ<EFBFBD><D6B5><EFBFBD>Ա<EFBFBD><D4B1>Ƚ<EFBFBD><C8BD>л<EFBFBD><D0BB>֣<EFBFBD>
|
||||
把表中的数据按照某种规则存储到多个结构相同的表中,例如按 id 的散列值、性别等进行划分,
|
||||
|
||||
**5. <EFBFBD><EFBFBD>ֱ<EFBFBD>з<EFBFBD><EFBFBD><EFBFBD>ˮƽ<EFBFBD>зֵ<EFBFBD>ѡ<EFBFBD><EFBFBD>**
|
||||
**5. 垂直切分与水平切分的选择**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>еı<EFBFBD>̫<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>ֱ<EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>
|
||||
如果数据库中的表太多,并且项目各项业务逻辑清晰,那么垂直切分是首选。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>ˮƽ<EFBFBD>з֡<EFBFBD>
|
||||
如果数据库的表不多,但是单表的数据量很大,应该选择水平切分。
|
||||
|
||||
**6. ˮƽ<EFBFBD>зֵ<EFBFBD>ʵ<EFBFBD>ַ<EFBFBD>ʽ**
|
||||
**6. 水平切分的实现方式**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> merge <EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD>档
|
||||
最简单的是使用 merge 存储引擎。
|
||||
|
||||
**7. <EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**7. 分库与分表存在的问题**
|
||||
|
||||
(1) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
(1) 事务问题
|
||||
|
||||
<EFBFBD><EFBFBD>ִ<EFBFBD>зֿ<EFBFBD><EFBFBD>ֱ<EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ洢<EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD>ͬ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿⱾ<EFBFBD><EFBFBD><EFBFBD>ķֲ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܴ<EFBFBD><EFBFBD>ۣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD>ȥЭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD>γɳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɱ<EFBFBD><EFBFBD>̷<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
|
||||
|
||||
(2) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
(2) 跨库跨表连接问题
|
||||
|
||||
<EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD>˷ֿ<EFBFBD><EFBFBD>ֱ<EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ὣԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ϡ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD>ֿ<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӷֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD>ͬ<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫһ<EFBFBD>β<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD>β<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>
|
||||
在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上。这时,表的连接操作将受到限制,我们无法连接位于不同分库的表,也无法连接分表粒度不同的表,导致原本只需要一次查询就能够完成的业务需要进行多次才能完成。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ƺ<EFBFBD><EFBFBD>ϻָ<EFBFBD>
|
||||
# 故障转移和故障恢复
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>⡣<EFBFBD><EFBFBD><EFBFBD>ϻָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵӹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>лָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ԡ<EFBFBD>
|
||||
故障转移也叫做切换,当主库出现故障时就切换到备库,使备库成为主库。故障恢复顾名思义就是从故障中恢复过来,并且保证数据的正确性。
|
||||
|
||||
## 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>
|
||||
## 1. 故障转移
|
||||
|
||||
**1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>ɫ**
|
||||
**1.1 提升备库或切换角色**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ̨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD>ƽṹ<C6BD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
|
||||
提升一台备库为主库,或者在一个主-主复制结构中调整主动和被动角色。
|
||||
|
||||
**1.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>ַ<EFBFBD><D6B7> IP <EFBFBD>й<EFBFBD>**
|
||||
**1.2 虚拟 IP 地址和 IP 托管**
|
||||
|
||||
Ϊ MySQL ʵ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP <20><>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD> MySQL ʵ<><CAB5>ʧЧʱ<D0A7><CAB1><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD> IP <20><>ַת<D6B7>Ƶ<EFBFBD><C6B5><EFBFBD>һ̨ MySQL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
为 MySQL 实例指定一个逻辑 IP 地址,当 MySQL 实例失效时,可以将 IP 地址转移到另一台 MySQL 服务器上。
|
||||
|
||||
**1.3 <EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1.3 中间件解决方案**
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
通过代理,可以路由流量到可以使用的服务器上。
|
||||
|
||||

|
||||

|
||||
|
||||
**1.4 <EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>**
|
||||
**1.4 在应用中处理故障转移**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>̫<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
将故障转移整合到应用中可能导致应用变得太过笨拙。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD>ϻָ<EFBFBD>
|
||||
## 2. 故障恢复
|
||||
|
||||
|
||||
# <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 参考资料
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> MySQL
|
||||
- [MySQL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽṹ<EFBFBD><EFBFBD><EFBFBD>㷨ԭ<EFBFBD><EFBFBD> ](http://blog.codinglabs.org/articles/theory-of-mysql-index.html)
|
||||
- [MySQL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ](http://www.runoob.com/w3cnote/mysql-index.html)
|
||||
- [20+ <EFBFBD><EFBFBD> MySQL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD> ](https://www.jfox.info/20-tiao-mysql-xing-nen-you-hua-de-zui-jia-jing-yan.html)
|
||||
- 高性能 MySQL
|
||||
- [MySQL 索引背后的数据结构及算法原理 ](http://blog.codinglabs.org/articles/theory-of-mysql-index.html)
|
||||
- [MySQL 索引优化全攻略 ](http://www.runoob.com/w3cnote/mysql-index.html)
|
||||
- [20+ 条 MySQL 性能优化的最佳经验 ](https://www.jfox.info/20-tiao-mysql-xing-nen-you-hua-de-zui-jia-jing-yan.html)
|
||||
|
503
notes/SQL 语法.md
503
notes/SQL 语法.md
@ -1,52 +1,53 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>ѯ](#<EFBFBD><EFBFBD>ѯ)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#ͨ<><CDA8><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>ʱ<EFBFBD>䴦<EFBFBD><EFBFBD>](#<23><><EFBFBD>ں<EFBFBD>ʱ<EFBFBD>䴦<EFBFBD><E4B4A6>)
|
||||
* [<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>Ӳ<EFBFBD>ѯ](#<EFBFBD>Ӳ<EFBFBD>ѯ)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>ѯ](#<23><><EFBFBD>ϲ<EFBFBD>ѯ)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [ɾ<EFBFBD><EFBFBD>](#ɾ<EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>ı<EFBFBD>](#<EFBFBD>ı<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>ͼ](#<EFBFBD><EFBFBD>ͼ)
|
||||
* [<EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>α<EFBFBD>](#<EFBFBD>α<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>](#<23>ַ<EFBFBD><D6B7><EFBFBD>)
|
||||
* [Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#Ȩ<><EFBFBD><DEB9><EFBFBD>)
|
||||
* [基础](#基础)
|
||||
* [查询](#查询)
|
||||
* [排序](#排序)
|
||||
* [过滤](#过滤)
|
||||
* [通配符](#通配符)
|
||||
* [计算字段](#计算字段)
|
||||
* [函数](#函数)
|
||||
* [文本处理](#文本处理)
|
||||
* [日期和时间处理](#日期和时间处理)
|
||||
* [数值处理](#数值处理)
|
||||
* [汇总](#汇总)
|
||||
* [分组](#分组)
|
||||
* [子查询](#子查询)
|
||||
* [连接](#连接)
|
||||
* [内连接](#内连接)
|
||||
* [自连接](#自连接)
|
||||
* [自然连接](#自然连接)
|
||||
* [外连接](#外连接)
|
||||
* [组合查询](#组合查询)
|
||||
* [插入](#插入)
|
||||
* [更新](#更新)
|
||||
* [删除](#删除)
|
||||
* [创建表](#创建表)
|
||||
* [修改表](#修改表)
|
||||
* [视图](#视图)
|
||||
* [存储过程](#存储过程)
|
||||
* [游标](#游标)
|
||||
* [触发器](#触发器)
|
||||
* [事务处理](#事务处理)
|
||||
* [字符集](#字符集)
|
||||
* [权限管理](#权限管理)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><><EFBFBD><EFBFBD>
|
||||
|
||||
ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ洢<EFBFBD><EFBFBD><EFBFBD>洢ʲô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ηֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>ͱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>
|
||||
# 基础
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
模式:定义了数据如何存储、存储什么样的数据以及数据如何分解等信息,数据库和表都有模式。
|
||||
|
||||
SQL<EFBFBD><EFBFBD>Structured Query Language)<29><><EFBFBD><EFBFBD> SQL <20><> ANSI <20><>ίԱ<CEAF><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD>Ϊ ANSI SQL<51><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DBMS <20><><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3><EFBFBD> PL/SQL<51><4C>Transact-SQL <20>ȡ<EFBFBD>
|
||||
主键的值不允许修改,也不允许复用(不能使用已经删除的主键值赋给新数据行的主键)。
|
||||
|
||||
# <20><>ѯ
|
||||
SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL,各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。
|
||||
|
||||
SQL <20><><EFBFBD>䲻<EFBFBD><E4B2BB><EFBFBD>ִ<EFBFBD>Сд<D0A1><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD> DBMS <20>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
# 查询
|
||||
|
||||
SQL 语句不区分大小写,但是数据库表名、列名和值是否区分依赖于具体的 DBMS 以及配置。
|
||||
|
||||
**DISTINCT**
|
||||
|
||||
<EFBFBD><EFBFBD>ֵֻͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Ρ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD>
|
||||
相同值只会出现一次。它作用于所有列,也就是说所有列的值都相同才算相同。
|
||||
|
||||
```sql
|
||||
SELECT DISTINCT col1, col2
|
||||
@ -55,9 +56,9 @@ FROM mytable;
|
||||
|
||||
**LIMIT**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ʼ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD> 0 <20><>ʼ<EFBFBD><CABC><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ 5 <20>е<EFBFBD> SQL<EFBFBD><EFBFBD>
|
||||
返回前 5 行的 SQL:
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
@ -71,7 +72,7 @@ FROM mytable
|
||||
LIMIT 0, 5;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD> 3 \~ 5 <EFBFBD>У<EFBFBD>
|
||||
返回第 3 \~ 5 行:
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
@ -79,22 +80,22 @@ FROM mytable
|
||||
LIMIT 2, 3;
|
||||
```
|
||||
|
||||
**ע<EFBFBD><EFBFBD>**
|
||||
**注释**
|
||||
|
||||
```sql
|
||||
# ע<EFBFBD><EFBFBD>
|
||||
# 注释
|
||||
SELECT *
|
||||
FROM mytable -- ע<EFBFBD><EFBFBD>
|
||||
/* ע<EFBFBD><EFBFBD>1
|
||||
ע<EFBFBD><EFBFBD>2 */
|
||||
FROM mytable -- 注释
|
||||
/* 注释1
|
||||
注释2 */
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 排序
|
||||
|
||||
**ASC**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϣ<EFBFBD>
|
||||
**DESC**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
**ASC**:升序(默认)
|
||||
**DESC**:降序
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可以按多个列进行排序:
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
@ -102,9 +103,9 @@ FROM mytable
|
||||
ORDER BY col1 DESC, col2 ASC;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 过滤
|
||||
|
||||
<EFBFBD><EFBFBD>Ӧ<EFBFBD>ò<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷdz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>紫<EFBFBD><EFBFBD><EFBFBD>˺ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD>˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在应用层也可以过滤数据,但是不在服务器端进行过滤的数据非常大,导致通过网络传输了很多多余的数据,从而浪费了网络带宽。
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
@ -112,155 +113,155 @@ FROM mytable
|
||||
WHERE col IS NULL;
|
||||
```
|
||||
|
||||
<EFBFBD>±<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD> WHERE <20>Ӿ<EFBFBD><D3BE><EFBFBD><EFBFBD>õIJ<C3B5><C4B2><EFBFBD><EFBFBD><EFBFBD>
|
||||
下表显示了 WHERE 子句可用的操作符
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 操作符 | 说明 |
|
||||
| ------------ | ------------ |
|
||||
| = < > | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> С<><D0A1> <20><><EFBFBD><EFBFBD> |
|
||||
| <> != | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| <= !> | С<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> |
|
||||
| >= !< | <EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> |
|
||||
| BETWEEN | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ֮<EFBFBD><EFBFBD> |
|
||||
| IS NULL | ΪNULLֵ |
|
||||
| = < > | 等于 小于 大于 |
|
||||
| <> != | 不等于 |
|
||||
| <= !> | 小于等于 |
|
||||
| >= !< | 大于等于 |
|
||||
| BETWEEN | 在两个值之间 |
|
||||
| IS NULL | 为NULL值 |
|
||||
|
||||
Ӧ<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>NULL <EFBFBD><EFBFBD> 0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD>
|
||||
应该注意到,NULL 与 0 、空字符串都不同。
|
||||
|
||||
**AND OR** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD> AND<4E><44><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>˱<EFBFBD><CBB1><EFBFBD>ʽ<EFBFBD>漰<EFBFBD><E6BCB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AND <EFBFBD><EFBFBD> OR ʱ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> () <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD>
|
||||
**AND OR** 用于连接多个过滤条件。优先处理 AND,因此当一个过滤表达式涉及到多个 AND 和 OR 时,应当使用 () 来决定优先级。
|
||||
|
||||
**IN** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD>һ<EFBFBD><EFBFBD> SELECT <20>Ӿ䣬<D3BE>Ӷ<EFBFBD>ƥ<EFBFBD><C6A5><EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD>һ<EFBFBD><D2BB>ֵ<EFBFBD><D6B5>
|
||||
**IN** 操作符用于匹配一组值,其后也可以接一个 SELECT 子句,从而匹配子查询得到的一组值。
|
||||
|
||||
**NOT** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
**NOT** 操作符用于否定一个条件。
|
||||
|
||||
# ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 通配符
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ֶΡ<EFBFBD>
|
||||
通配符也是用在过滤语句中,只能用于文本字段。
|
||||
|
||||
- **%** ƥ<EFBFBD><EFBFBD> >=0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \*<EFBFBD><EFBFBD>
|
||||
- **%** 匹配 >=0 个任意字符,类似于 \*;
|
||||
|
||||
- **\_** ƥ<EFBFBD><EFBFBD> ==1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \.<EFBFBD><EFBFBD>
|
||||
- **\_** 匹配 ==1 个任意字符,类似于 \.;
|
||||
|
||||
- **[ ]** <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD>伯<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD> ^ <20><><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><D0B7><EFBFBD>
|
||||
- **[ ]** 可以匹配集合内的字符,用脱字符 ^ 可以对其进行否定
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> Like <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD>䡣
|
||||
使用 Like 来进行通配符匹配。
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM mytable
|
||||
WHERE col LIKE '[^AB]%' -- <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AB<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
|
||||
WHERE col LIKE '[^AB]%' -- 不以AB开头的任意文本
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ڿ<EFBFBD>ͷ<EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
不要滥用通配符,通配符位于开头处匹配会非常慢。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
# 计算字段
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><EFBFBD>ö࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٵĻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在数据库服务器上完成数据的转换和格式化的工作往往比客户端上快得多,并且转换和格式化后的数据量更少的话可以减少网络通信量。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD> **AS** <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>
|
||||
计算字段通常需要使用 **AS** 来取别名,否则输出的时候字段名为计算表达式。
|
||||
|
||||
```sql
|
||||
SELECT col1*col2 AS alias
|
||||
FROM mytable
|
||||
```
|
||||
|
||||
**Concat()** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ÿո<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ŀո<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> **TRIM()** <20><><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD>β<EFBFBD>ո<EFBFBD><D5B8><EFBFBD>
|
||||
**Concat()** 用于连接两个字段。许多数据库会使用空格把一个值填充为列宽,因此连接的结果会出现一些不必要的空格,使用 **TRIM()** 可以去除首尾空格。
|
||||
|
||||
```sql
|
||||
SELECT Concat(TRIM(col1), ' (', TRIM(col2), ')')
|
||||
FROM mytable
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 函数
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> DBMS <EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>
|
||||
各个 DBMS 的函数都是不相同的,因此不可移植。
|
||||
|
||||
## <EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 文本处理
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ˵<EFBFBD><EFBFBD> |
|
||||
| 函数 | 说明 |
|
||||
| ------------ | ------------ |
|
||||
| LEFT() RIGHT() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵ<EFBFBD><EFBFBD>ַ<EFBFBD> |
|
||||
| LOWER() UPPER() | ת<EFBFBD><EFBFBD>ΪСд<EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>д |
|
||||
| LTRIM() RTIM() | ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵĿո<EFBFBD> |
|
||||
| LENGTH() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| SUNDEX() | ת<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ |
|
||||
| LEFT() RIGHT() | 左边或者右边的字符 |
|
||||
| LOWER() UPPER() | 转换为小写或者大写 |
|
||||
| LTRIM() RTIM() | 去除左边或者右边的空格 |
|
||||
| LENGTH() | 长度 |
|
||||
| SUNDEX() | 转换为语音值 |
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>**SOUNDEX()** <EFBFBD>ǽ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><EFBFBD>ݷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>Ƚϡ<EFBFBD>
|
||||
其中,**SOUNDEX()** 是将一个字符串转换为描述其语音表示的字母数字模式的算法,它是根据发音而不是字母比较。
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
FROM mytable
|
||||
WHERE SOUNDEX(col1) = SOUNDEX('apple')
|
||||
```
|
||||
## <EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>ʱ<EFBFBD>䴦<EFBFBD><EFBFBD>
|
||||
## 日期和时间处理
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>ʽ<EFBFBD><EFBFBD>YYYY-MM-DD
|
||||
日期格式:YYYY-MM-DD
|
||||
|
||||
ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>HH:MM:SS
|
||||
时间格式:HH:MM:SS
|
||||
|
||||
|<EFBFBD><EFBFBD> <20><> | ˵ <20><>|
|
||||
|函 数 | 说 明|
|
||||
| --- | --- |
|
||||
| AddDate() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD>졢<EFBFBD>ܵȣ<EFBFBD>|
|
||||
| AddTime() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD>䣨ʱ<EFBFBD><EFBFBD><EFBFBD>ֵȣ<EFBFBD>|
|
||||
| CurDate() | <EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| CurTime() | <EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ǰʱ<EFBFBD><EFBFBD> |
|
||||
|Date() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>|
|
||||
|DateDiff() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>|
|
||||
|Date_Add() |<EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㺯<EFBFBD><EFBFBD>|
|
||||
|Date_Format() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD>ʱ<EFBFBD>䴮|
|
||||
|Day()| <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
|DayOfWeek() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>|
|
||||
|Hour() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Сʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
|Minute() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>|
|
||||
|Month() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD>·ݲ<EFBFBD><EFBFBD><EFBFBD>|
|
||||
|Now() |<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>ʱ<EFBFBD><EFBFBD>|
|
||||
|Second() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>벿<EFBFBD><EFBFBD>|
|
||||
|Time() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䲿<EFBFBD><EFBFBD>|
|
||||
|Year() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD>|
|
||||
| AddDate() | 增加一个日期(天、周等)|
|
||||
| AddTime() | 增加一个时间(时、分等)|
|
||||
| CurDate() | 返回当前日期 |
|
||||
| CurTime() | 返回当前时间 |
|
||||
|Date() |返回日期时间的日期部分|
|
||||
|DateDiff() |计算两个日期之差|
|
||||
|Date_Add() |高度灵活的日期运算函数|
|
||||
|Date_Format() |返回一个格式化的日期或时间串|
|
||||
|Day()| 返回一个日期的天数部分|
|
||||
|DayOfWeek() |对于一个日期,返回对应的星期几|
|
||||
|Hour() |返回一个时间的小时部分|
|
||||
|Minute() |返回一个时间的分钟部分|
|
||||
|Month() |返回一个日期的月份部分|
|
||||
|Now() |返回当前日期和时间|
|
||||
|Second() |返回一个时间的秒部分|
|
||||
|Time() |返回一个日期时间的时间部分|
|
||||
|Year() |返回一个日期的年份部分|
|
||||
|
||||
```sql
|
||||
mysql> SELECT NOW();
|
||||
-> '2017-06-28 14:01:52'
|
||||
```
|
||||
|
||||
## <EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 数值处理
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ˵<><CBB5> |
|
||||
| 函数 | 说明 |
|
||||
| --- | --- |
|
||||
| SIN() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
|COS() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| TAN() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
| ABS() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ |
|
||||
| SQRT() | ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
| MOD() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
| EXP() | ָ<EFBFBD><EFBFBD>|
|
||||
| PI() | Բ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
|RAND() | <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
| SIN() | 正弦 |
|
||||
|COS() | 余弦 |
|
||||
| TAN() | 正切 |
|
||||
| ABS() | 绝对值 |
|
||||
| SQRT() | 平方根|
|
||||
| MOD() | 余数|
|
||||
| EXP() | 指数|
|
||||
| PI() | 圆周率|
|
||||
|RAND() | 随机数|
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 汇总
|
||||
|
||||
|<EFBFBD><EFBFBD> <20><> |˵ <20><>|
|
||||
|函 数 |说 明|
|
||||
| --- | --- |
|
||||
|AVG() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>е<EFBFBD>ƽ<EFBFBD><EFBFBD>ֵ|
|
||||
|COUNT()| <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>|
|
||||
|MAX()| <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ|
|
||||
|MIN()| <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Сֵ|
|
||||
|SUM() |<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD>ֵ֮<EFBFBD><EFBFBD>|
|
||||
|AVG() |返回某列的平均值|
|
||||
|COUNT()| 返回某列的行数|
|
||||
|MAX()| 返回某列的最大值|
|
||||
|MIN()| 返回某列的最小值|
|
||||
|SUM() |返回某列值之和|
|
||||
|
||||
AVG() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NULL <EFBFBD>С<EFBFBD>
|
||||
AVG() 会忽略 NULL 行。
|
||||
|
||||
DISTINCT <EFBFBD>ؼ<EFBFBD><EFBFBD>ֻ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ܲ<EFBFBD>ͬ<EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>
|
||||
DISTINCT 关键字会只汇总不同的值。
|
||||
|
||||
```sql
|
||||
SELECT AVG(DISTINCT col1) AS avg_col
|
||||
FROM mytable
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 分组
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
分组就是把相同的数据放在同一组中。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>û<EFBFBD><EFBFBD>ܺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD>ֵ<EFBFBD>ȡ<EFBFBD>
|
||||
可以对每组数据使用汇总函数进行处理,例如求每组数的平均值等。
|
||||
|
||||
<EFBFBD><EFBFBD> col <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
按 col 排序并分组数据:
|
||||
|
||||
```sql
|
||||
SELECT col, COUNT(*) AS num
|
||||
@ -268,7 +269,7 @@ FROM mytable
|
||||
GROUP BY col;
|
||||
```
|
||||
|
||||
WHERE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>HAVING <20><><EFBFBD>˷<EFBFBD><CBB7>飬<EFBFBD>й<EFBFBD><D0B9><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
|
||||
WHERE 过滤行,HAVING 过滤分组,行过滤应当先与分组过滤;
|
||||
|
||||
```sql
|
||||
SELECT col, COUNT(*) AS num
|
||||
@ -278,7 +279,7 @@ GROUP BY col
|
||||
HAVING COUNT(*) >= 2;
|
||||
```
|
||||
|
||||
GROUP BY <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΣ<EFBFBD><EFBFBD><EFBFBD> ORDER BY Ҳ<><D2B2><EFBFBD><EFBFBD><EFBFBD>Ծۼ<D4BE><DBBC>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
GROUP BY 的排序结果为分组字段,而 ORDER BY 也可以以聚集字段来进行排序。
|
||||
|
||||
```sql
|
||||
SELECT col, COUNT(*) AS num
|
||||
@ -287,18 +288,18 @@ GROUP BY col
|
||||
ORDER BY num;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>涨<EFBFBD><EFBFBD>
|
||||
分组规定:
|
||||
|
||||
1. GROUP BY <EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> WHERE <20>Ӿ<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ORDER BY <EFBFBD>Ӿ<EFBFBD>֮ǰ<EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD><EFBFBD>ܼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>⣬SELECT <20><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ÿһ<C3BF>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> GROUP BY <20>Ӿ<EFBFBD><D3BE>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD>
|
||||
3. NULL <EFBFBD><EFBFBD><EFBFBD>лᵥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһ<EFBFBD>飻
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SQL ʵ<>ֲ<EFBFBD>֧<EFBFBD><D6A7> GROUP BY <20>о<EFBFBD><D0BE>пɱ䳤<C9B1>ȵ<EFBFBD><C8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
1. GROUP BY 子句出现在 WHERE 子句之后,ORDER BY 子句之前;
|
||||
2. 除了汇总计算语句之外,SELECT 语句中的每一列都必须在 GROUP BY 子句中给出;
|
||||
3. NULL 的行会单独分为一组;
|
||||
4. 大多数 SQL 实现不支持 GROUP BY 列具有可变长度的数据类型。
|
||||
|
||||
# <EFBFBD>Ӳ<EFBFBD>ѯ
|
||||
# 子查询
|
||||
|
||||
<EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD><EFBFBD>ֻ<EFBFBD>ܷ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
子查询中只能返回一个列。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ WHRER <20><><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可以将子查询的结果作为 WHRER 语句的过滤条件:
|
||||
|
||||
```
|
||||
SELECT *
|
||||
@ -307,7 +308,7 @@ WHERE col1 IN (SELECT col2
|
||||
FROM mytable2);
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD>ִ<EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD>
|
||||
下面的语句可以检索出客户的订单数量。子查询语句会对检索出的每个客户执行一次:
|
||||
|
||||
```sql
|
||||
SELECT cust_name, (SELECT COUNT(*)
|
||||
@ -318,17 +319,17 @@ FROM Customers
|
||||
ORDER BY cust_name;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> JOIN <20>ؼ<EFBFBD><D8BC>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> ON<EFBFBD><EFBFBD>
|
||||
连接用于连接多个表,使用 JOIN 关键字,并且条件语句使用 ON。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻<EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD><EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>졣
|
||||
连接可以替换子查询,并且比子查询的效率一般会更快。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶκͱ<CEBA><CDB1><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>˼<EFBFBD><CBBC><EFBFBD> SQL <20><><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>
|
||||
可以用 AS 给列名、计算字段和表名取别名,给表名取别名是为了简化 SQL 语句以及连接相同表。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 内连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳƵ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>ʹ<EFBFBD><EFBFBD> INNER JOIN <EFBFBD>ؼ<EFBFBD><EFBFBD>֡<EFBFBD>
|
||||
内连接又称等值连接,使用 INNER JOIN 关键字。
|
||||
|
||||
```
|
||||
select a, b, c
|
||||
@ -336,7 +337,7 @@ from A inner join B
|
||||
on A.key = B.key
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>ȷʹ<EFBFBD><EFBFBD> INNER JOIN<49><4E><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> WHERE <20>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>õ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可以不明确使用 INNER JOIN,而使用普通查询并在 WHERE 中将两个表中要连接的列用等值方法连接起来。
|
||||
|
||||
```
|
||||
select a, b, c
|
||||
@ -344,15 +345,15 @@ from A, B
|
||||
where A.key = B.key
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><EFBFBD>صѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在没有条件语句的情况下返回笛卡尔积。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 自连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>һ<EFBFBD>֣<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>
|
||||
自连接可以看成内连接的一种,只是连接的表是自身而已。
|
||||
|
||||
һ<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>Ҫ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD> Jim <20><><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
一张员工表,包含员工姓名和员工所属部门,要找出与 Jim 处在同一部门的所有员工姓名。
|
||||
|
||||
**<EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD>汾**
|
||||
**子查询版本**
|
||||
|
||||
```
|
||||
select name
|
||||
@ -363,7 +364,7 @@ where department = (
|
||||
where name = "Jim");
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ汾**
|
||||
**自连接版本**
|
||||
|
||||
```
|
||||
select name
|
||||
@ -372,24 +373,24 @@ where e1.department = e2.department
|
||||
and e1.name = "Jim";
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD>ѯ<EFBFBD><EFBFBD>Ч<EFBFBD>ʸߡ<EFBFBD>
|
||||
连接一般比子查询的效率高。
|
||||
|
||||
## <EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 自然连接
|
||||
|
||||
<EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
自然连接是把同名列通过等值测试连接起来的,同名列可以有多个。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӻ<EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
内连接和自然连接的区别:内连接提供连接的列,而自然连接自动连接所有同名列;内连接属于自然连接。
|
||||
|
||||
```
|
||||
select *
|
||||
from employee natural join department;
|
||||
```
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 外连接
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӿ<EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
外连接保留了没有关联的那些行。分为左外连接,右外连接以及全外连接,左外连接就是保留左表的所有行。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й˿͵Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>Ĺ˿͡<EFBFBD>
|
||||
检索所有顾客的订单信息,包括还没有订单信息的顾客。
|
||||
|
||||
```
|
||||
select Customers.cust_id, Orders.order_num
|
||||
@ -397,7 +398,7 @@ select Customers.cust_id, Orders.order_num
|
||||
on Customers.cust_id = Orders.curt_id
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫͳ<EFBFBD>ƹ˿͵Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>þۼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
如果需要统计顾客的订单数,使用聚集函数。
|
||||
|
||||
```
|
||||
select Customers.cust_id,
|
||||
@ -407,13 +408,13 @@ on Customers.cust_id = Orders.curt_id
|
||||
group by Customers.cust_id
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD>ѯ
|
||||
# 组合查询
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> **UNION** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>߾ۼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
使用 **UNION** 来连接两个查询,每个查询必须包含相同的列、表达式或者聚集函数。
|
||||
|
||||
Ĭ<EFBFBD>ϻ<EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>У<EFBFBD>ʹ<EFBFBD><EFBFBD> UNION ALL <EFBFBD><EFBFBD>
|
||||
默认会去除相同行,如果需要保留相同行,使用 UNION ALL 。
|
||||
|
||||
ֻ<EFBFBD>ܰ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> ORDER BY <EFBFBD>Ӿ䣬<EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
只能包含一个 ORDER BY 子句,并且必须位于语句的最后。
|
||||
|
||||
```sql
|
||||
SELECT col
|
||||
@ -425,16 +426,16 @@ FROM mytable
|
||||
WHERE col =2;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 插入
|
||||
|
||||
**<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**普通插入**
|
||||
|
||||
```sql
|
||||
INSERT INTO mytable(col1, col2)
|
||||
VALUES(val1, val2);
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**插入检索出来的数据**
|
||||
|
||||
```sql
|
||||
INSERT INTO mytable1(col1, col2)
|
||||
@ -442,14 +443,14 @@ SELECT col1, col2
|
||||
FROM mytable2;
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><EFBFBD>Ƶ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>**
|
||||
**将一个表的内容复制到一个新表**
|
||||
|
||||
```sql
|
||||
CREATE TABLE newtable AS
|
||||
SELECT * FROM mytable;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 更新
|
||||
|
||||
```sql
|
||||
UPDATE mytable
|
||||
@ -457,18 +458,18 @@ SET col = val
|
||||
WHERE id = 1;
|
||||
```
|
||||
|
||||
# ɾ<EFBFBD><EFBFBD>
|
||||
# 删除
|
||||
|
||||
```sql
|
||||
DELETE FROM mytable
|
||||
WHERE id = 1;
|
||||
```
|
||||
|
||||
**TRUNCATE TABLE** <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ձ<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
**TRUNCATE TABLE** 可以清空表,也就是删除所有行。
|
||||
|
||||
ʹ<EFBFBD>ø<EFBFBD><EFBFBD>º<EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱһ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> WHERE <20>Ӿ䣬<D3BE><E4A3AC>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><DDB6>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SELECT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2>ԣ<EFBFBD><D4A3><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>
|
||||
使用更新和删除操作时一定要用 WHERE 子句,不然会把整张表的数据都破坏。可以先用 SELECT 语句进行测试,防止错误删除。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 创建表
|
||||
|
||||
```sql
|
||||
CREATE TABLE mytable (
|
||||
@ -479,38 +480,38 @@ CREATE TABLE mytable (
|
||||
PRIMARY KEY (`id`));
|
||||
```
|
||||
|
||||
# <EFBFBD>ı<EFBFBD>
|
||||
# 修改表
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**添加列**
|
||||
|
||||
```sql
|
||||
ALTER TABLE mytable
|
||||
ADD col CHAR(20);
|
||||
```
|
||||
|
||||
**ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**删除列**
|
||||
|
||||
```sql
|
||||
ALTER TABLE mytable
|
||||
DROP COLUMN col;
|
||||
```
|
||||
|
||||
**ɾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**删除表**
|
||||
|
||||
```sql
|
||||
DROP TABLE mytable;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD>ͼ
|
||||
# 视图
|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>Ҳ<EFBFBD>Ͳ<EFBFBD><EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
视图是虚拟的表,本身不包含数据,也就不能对其进行索引操作。对视图的操作和对普通表的操作一样。
|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ºô<EFBFBD><EFBFBD><EFBFBD>
|
||||
视图具有如下好处:
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD> SQL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>縴<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>
|
||||
2. ֻʹ<EFBFBD><EFBFBD>ʵ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
3. ͨ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>Ȩ<EFBFBD>ޣ<EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD>ݵİ<EFBFBD>ȫ<EFBFBD>ԣ<EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD>ʽ<EFBFBD>ͱ<EFBFBD>ʾ<EFBFBD><EFBFBD>
|
||||
1. 简化复杂的 SQL 操作,比如复杂的联结;
|
||||
2. 只使用实际表的一部分数据;
|
||||
3. 通过只给用户访问视图的权限,保证数据的安全性;
|
||||
4. 更改数据格式和表示。
|
||||
|
||||
```sql
|
||||
CREATE VIEW myview AS
|
||||
@ -519,25 +520,25 @@ FROM mytable
|
||||
WHERE col5 = val;
|
||||
```
|
||||
|
||||
# <EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 存储过程
|
||||
|
||||
<EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD>̿<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD>һϵ<EFBFBD><EFBFBD> SQL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
存储过程可以看成是对一系列 SQL 操作的批处理;
|
||||
|
||||
**ʹ<EFBFBD>ô洢<EFBFBD><EFBFBD><EFBFBD>̵ĺô<EFBFBD>**
|
||||
**使用存储过程的好处**
|
||||
|
||||
1. <EFBFBD><EFBFBD>ʵ<EFBFBD>ַ<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>˴洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>֤<EFBFBD>˰<EFBFBD>ȫ<EFBFBD>ԣ<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>룻
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD>ȱ<EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD>˾<EFBFBD><EFBFBD>кܸߵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
1. 把实现封装在了存储过程中,不仅简单,也保证了安全性;
|
||||
2. 可以复用代码;
|
||||
3. 由于是预先编译,因此具有很高的性能。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**创建存储过程**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ; Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>˷ֺţ<D6BA><C5A3><EFBFBD><EFBFBD>˻<EFBFBD><CBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>ַֺŵ<D6BA><C5B5><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFB7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
命令行中创建存储过程需要自定义分隔符,因为命令行是以 ; 为结束符,而存储过程中也包含了分号,因此会错误把这部分分号当成是结束符,造成语法错误。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> in<EFBFBD><EFBFBD>out <EFBFBD><EFBFBD> inout <EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
包含 in、out 和 inout 三种参数。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> select into <EFBFBD><EFBFBD><EFBFBD>䡣
|
||||
给变量赋值都需要用 select into 语句。
|
||||
|
||||
ÿ<EFBFBD><EFBFBD>ֻ<EFBFBD>ܸ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD>ּ<EFBFBD><EFBFBD>ϵIJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
每次只能给一个变量赋值,不支持集合的操作。
|
||||
|
||||
```sql
|
||||
delimiter //
|
||||
@ -558,18 +559,18 @@ call myprocedure(@ret);
|
||||
select @ret;
|
||||
```
|
||||
|
||||
# <EFBFBD>α<EFBFBD>
|
||||
# 游标
|
||||
|
||||
<EFBFBD>ڴ洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>α<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在存储过程中使用游标可以对一个结果集进行移动遍历。
|
||||
|
||||
<EFBFBD>α<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD>ʽӦ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
游标主要用于交互式应用,其中用户需要对数据集中的任意行进行浏览和修改。
|
||||
|
||||
**ʹ<EFBFBD><EFBFBD><EFBFBD>α<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>裺**
|
||||
**使用游标的四个步骤:**
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>α꣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>ʵ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>αꣻ
|
||||
3. ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>
|
||||
4. <EFBFBD>ر<EFBFBD><EFBFBD>αꣻ
|
||||
1. 声明游标,这个过程没有实际检索出数据;
|
||||
2. 打开游标;
|
||||
3. 取出数据;
|
||||
4. 关闭游标;
|
||||
|
||||
```sql
|
||||
delimiter //
|
||||
@ -579,7 +580,7 @@ create procedure myprocedure(out ret int)
|
||||
|
||||
declare mycursor cursor for
|
||||
select col1 from mytable;
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>continue handler<EFBFBD><EFBFBD><EFBFBD><EFBFBD> sqlstate '02000' <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> set done = 1
|
||||
# 定义了一个continue handler,当 sqlstate '02000' 这个条件出现时,会执行 set done = 1
|
||||
declare continue handler for sqlstate '02000' set done = 1;
|
||||
|
||||
open mycursor;
|
||||
@ -594,43 +595,43 @@ create procedure myprocedure(out ret int)
|
||||
delimiter ;
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 触发器
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ִ<EFBFBD>У<EFBFBD>DELETE<EFBFBD><EFBFBD>INSERT<EFBFBD><EFBFBD>UPDATE
|
||||
触发器会在某个表执行以下语句时而自动执行:DELETE、INSERT、UPDATE
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ִ<EFBFBD>У<EFBFBD>֮ǰִ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> BEFORE <20>ؼ<EFBFBD><D8BC>֣<EFBFBD>֮<EFBFBD><D6AE>ִ<EFBFBD><D6B4>ʹ<EFBFBD><CAB9> AFTER <EFBFBD>ؼ<EFBFBD><EFBFBD>֡<EFBFBD>BEFORE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
触发器必须指定在语句执行之前还是之后自动执行,之前执行使用 BEFORE 关键字,之后执行使用 AFTER 关键字。BEFORE 用于数据验证和净化。
|
||||
|
||||
INSERT <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ NEW <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
INSERT 触发器包含一个名为 NEW 的虚拟表。
|
||||
|
||||
```sql
|
||||
CREATE TRIGGER mytrigger AFTER INSERT ON mytable
|
||||
FOR EACH ROW SELECT NEW.col;
|
||||
```
|
||||
|
||||
DELETE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ OLD <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD>ġ<EFBFBD>
|
||||
DELETE 触发器包含一个名为 OLD 的虚拟表,并且是只读的。
|
||||
|
||||
UPDATE <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ NEW <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ϊ OLD <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NEW <20>ǿ<EFBFBD><C7BF>Ա<EFBFBD><D4B1>ĵأ<C4B5><D8A3><EFBFBD> OLD <20><>ֻ<EFBFBD><D6BB><EFBFBD>ġ<EFBFBD>
|
||||
UPDATE 触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表,其中 NEW 是可以被修改地,而 OLD 是只读的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƹ<EFBFBD><EFBFBD>٣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ű<EFBFBD><EFBFBD>С<EFBFBD>
|
||||
可以使用触发器来进行审计跟踪,把修改记录到另外一张表中。
|
||||
|
||||
MySQL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> CALL <20><><EFBFBD><EFBFBD> <20><>Ҳ<EFBFBD><D2B2><EFBFBD>Dz<EFBFBD><C7B2>ܵ<EFBFBD><DCB5>ô洢<C3B4><E6B4A2><EFBFBD>̡<EFBFBD>
|
||||
MySQL 不允许在触发器中使用 CALL 语句 ,也就是不能调用存储过程。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 事务处理
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**基本术语**
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>transaction<EFBFBD><EFBFBD>ָһ<EFBFBD><EFBFBD> SQL <EFBFBD><EFBFBD><EFBFBD>䣻
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>rollback<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> SQL <20><><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9>̣<EFBFBD>
|
||||
3. <EFBFBD>ύ<EFBFBD><EFBFBD>commit<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>δ<EFBFBD>洢<EFBFBD><EFBFBD> SQL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD>
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣨savepoint<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD>ʱռλ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>placeholder<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1. 事务(transaction)指一组 SQL 语句;
|
||||
2. 回退(rollback)指撤销指定 SQL 语句的过程;
|
||||
3. 提交(commit)指将未存储的 SQL 语句结果写入数据库表;
|
||||
4. 保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD> SELECT <EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD> SELECT <20><><EFBFBD><EFBFBD>Ҳû<D2B2><C3BB><EFBFBD>壻Ҳ<E5A3BB><D2B2><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD> CRETE <EFBFBD><EFBFBD> DROP <EFBFBD><EFBFBD><EFBFBD>䡣
|
||||
不能回退 SELECT 语句,回退 SELECT 语句也没意义;也不能回退 CRETE 和 DROP 语句。
|
||||
|
||||
MySQL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ύĬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ύ<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿִ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>ύһ<EFBFBD>Ρ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> START TRANSACTION <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>ʽ<EFBFBD>ύ<EFBFBD><E1BDBB><EFBFBD><EFBFBD> COMMIT <EFBFBD><EFBFBD> ROLLBACK <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>к<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD>رգ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>»ָ<EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ύ<EFBFBD><EFBFBD>
|
||||
MySQL 的事务提交默认是隐式提交,也就是每执行一条语句就会提交一次。当出现 START TRANSACTION 语句时,会关闭隐式提交;当 COMMIT 或 ROLLBACK 语句执行后,事务会自动关闭,重新恢复隐式提交。
|
||||
|
||||
ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> autocommit Ϊ 0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD>ύ<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD> autocommit <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 1 <20>Ż<EFBFBD><C5BB>ύ<EFBFBD><E1BDBB>autocommit <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
通过设置 autocommit 为 0 可以取消自动提交,直到 autocommit 被设置为 1 才会提交;autocommit 标记是针对每个连接而不是针对服务器的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬ROLLBACK <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD> START TRANSACTION <EFBFBD><EFBFBD><EFBFBD>䴦<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˱<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ROLLBACK <20><>ָ<EFBFBD><D6B8><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD>㣬<EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><CBB5>ñ<EFBFBD><C3B1><EFBFBD><EFBFBD>㡣
|
||||
如果没有设置保留点,ROLLBACK 会回退到 START TRANSACTION 语句处;如果设置了保留点,并且在 ROLLBACK 中指定该保留点,则会回退到该保留点。
|
||||
|
||||
```sql
|
||||
START TRANSACTION
|
||||
@ -642,15 +643,15 @@ ROLLBACK TO delete1
|
||||
COMMIT
|
||||
```
|
||||
|
||||
# <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
# 字符集
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**基本术语**
|
||||
|
||||
1. <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ĸ<EFBFBD>ͷ<EFBFBD><EFBFBD>ŵļ<EFBFBD><EFBFBD>ϣ<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊij<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>
|
||||
3. У<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>αȽϣ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>顣
|
||||
1. 字符集为字母和符号的集合;
|
||||
2. 编码为某个字符集成员的内部表示;
|
||||
3. 校对字符指定如何比较,主要用于排序和分组。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD>⣬Ҳ<EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
除了给表指定字符集和校对外,也可以给列指定:
|
||||
|
||||
```sql
|
||||
CREATE TABLE mytable
|
||||
@ -658,7 +659,7 @@ CREATE TABLE mytable
|
||||
DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱָ<EFBFBD><EFBFBD>У<EFBFBD>ԣ<EFBFBD>
|
||||
可以在排序、分组时指定校对:
|
||||
|
||||
```sql
|
||||
SELECT *
|
||||
@ -666,67 +667,67 @@ FROM mytable
|
||||
ORDER BY col COLLATE latin1_general_ci;
|
||||
```
|
||||
|
||||
# Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 权限管理
|
||||
|
||||
MySQL <EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> mysql <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF>С<EFBFBD>
|
||||
MySQL 的账户信息保存在 mysql 这个数据库中。
|
||||
|
||||
```sql
|
||||
USE mysql;
|
||||
SELECT user FROM user;
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>**
|
||||
**创建账户**
|
||||
|
||||
```sql
|
||||
CREATE USER myuser IDENTIFIED BY 'mypassword';
|
||||
```
|
||||
|
||||
<EFBFBD>´<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>Ȩ<EFBFBD>ޡ<EFBFBD>
|
||||
新创建的账户没有任何权限。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD><EFBFBD><EFBFBD>**
|
||||
**修改账户名**
|
||||
|
||||
```sql
|
||||
RENAME myuser TO newuser;
|
||||
```
|
||||
|
||||
**ɾ<EFBFBD><EFBFBD><EFBFBD>˻<EFBFBD>**
|
||||
**删除账户**
|
||||
|
||||
```sql
|
||||
DROP USER myuser;
|
||||
```
|
||||
|
||||
**<EFBFBD>鿴Ȩ<EFBFBD><EFBFBD>**
|
||||
**查看权限**
|
||||
|
||||
```sql
|
||||
SHOW GRANTS FOR myuser;
|
||||
```
|
||||

|
||||

|
||||
|
||||
<EFBFBD>˻<EFBFBD><EFBFBD><EFBFBD> username@host <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>壬username@% ʹ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
账户用 username@host 的形式定义,username@% 使用的是默认主机名。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD>**
|
||||
**授予权限**
|
||||
|
||||
```sql
|
||||
GRANT SELECT, INSERT ON mydatabase.* TO myuser;
|
||||
```
|
||||
|
||||
**ɾ<EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD>**
|
||||
**删除权限**
|
||||
|
||||
```sql
|
||||
REVOKE SELECT, INSERT ON mydatabase.* FROM myuser;
|
||||
```
|
||||
|
||||
GRANT <EFBFBD><EFBFBD> REVOKE <EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD>ޣ<EFBFBD>
|
||||
GRANT 和 REVOKE 可在几个层次上控制访问权限:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> GRANT ALL<EFBFBD><EFBFBD> REVOKE ALL<EFBFBD><EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ⣬ʹ<EFBFBD><EFBFBD> ON database.\*<EFBFBD><EFBFBD>
|
||||
- <EFBFBD>ض<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> ON database.table<EFBFBD><EFBFBD>
|
||||
- <EFBFBD>ض<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>
|
||||
- <EFBFBD>ض<EFBFBD><EFBFBD>Ĵ洢<EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
- 整个服务器,使用 GRANT ALL和 REVOKE ALL;
|
||||
- 整个数据库,使用 ON database.\*;
|
||||
- 特定的表,使用 ON database.table;
|
||||
- 特定的列;
|
||||
- 特定的存储过程。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**更改密码**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> Password() <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
必须使用 Password() 函数
|
||||
|
||||
```sql
|
||||
SET PASSWROD FOR myuser = Password('newpassword');
|
||||
|
193
notes/代码可读性.md
193
notes/代码可读性.md
@ -1,90 +1,91 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD>ɶ<EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>](#<23>ɶ<EFBFBD><C9B6>Ե<EFBFBD><D4B5><EFBFBD>Ҫ<EFBFBD><D2AA>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뺬<EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뺬<EFBFBD><EBBAAC>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>ܴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD>ֲ<EFBFBD><D6B2>ܴ<EFBFBD><DCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>õĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD>õĴ<C3B5><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>дע<EFBFBD><EFBFBD>](#<23><>дע<D0B4><D7A2>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>α<EFBFBD>дע<EFBFBD><EFBFBD>](#<23><><EFBFBD>α<EFBFBD>дע<D0B4><D7A2>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀɶ<EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD>߿<EFBFBD><DFBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀɶ<C4BF><C9B6><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ](#<23><><EFBFBD>ֳ<EFBFBD><D6B3><EFBFBD><EFBFBD><EFBFBD>ʽ)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>)
|
||||
* [һ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#һ<><D2BB>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD>ٴ<EFBFBD><D9B4><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [可读性的重要性](#可读性的重要性)
|
||||
* [用名字表达代码含义](#用名字表达代码含义)
|
||||
* [名字不能带来歧义](#名字不能带来歧义)
|
||||
* [良好的代码风格](#良好的代码风格)
|
||||
* [编写注释](#编写注释)
|
||||
* [如何编写注释](#如何编写注释)
|
||||
* [提高控制流的可读性](#提高控制流的可读性)
|
||||
* [拆分长表达式](#拆分长表达式)
|
||||
* [变量与可读性](#变量与可读性)
|
||||
* [抽取函数](#抽取函数)
|
||||
* [一次只做一件事](#一次只做一件事)
|
||||
* [用自然语言表述代码](#用自然语言表述代码)
|
||||
* [减少代码量](#减少代码量)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20>ɶ<EFBFBD><C9B6>Ե<EFBFBD><D4B5><EFBFBD>Ҫ<EFBFBD><D2AA>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܴ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ķ<EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵Ĵ<EFBFBD><EFBFBD>롣<EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ʡ<EFBFBD>
|
||||
# 可读性的重要性
|
||||
|
||||
<EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>ִ<EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
编程有很大一部分时间是在阅读代码,不仅要阅读自己的代码,而且要阅读别人的代码。因此,可读性良好的代码能够大大提高编程效率。
|
||||
|
||||
ֻ<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>Ч<EFBFBD>ʲſ<EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һλ<EFBFBD><EFBFBD>
|
||||
可读性良好的代码往往会让代码架构更好,因为程序员更愿意去修改这部分代码,而且也更容易修改。
|
||||
|
||||
# <20><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뺬<EFBFBD><EBBAAC>
|
||||
只有在核心领域为了效率才可以放弃可读性,否则可读性是第一位。
|
||||
|
||||
һЩ<EFBFBD>Ƚ<EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD>ʣ<EFBFBD>
|
||||
# 用名字表达代码含义
|
||||
|
||||
| <20><><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
一些比较有表达力的单词:
|
||||
|
||||
| 单词 | 可替代单词 |
|
||||
| --- | --- |
|
||||
| send | deliver<EFBFBD><EFBFBD>dispatch<EFBFBD><EFBFBD>announce<EFBFBD><EFBFBD>distribute<EFBFBD><EFBFBD>route |
|
||||
| find | search<EFBFBD><EFBFBD>extract<EFBFBD><EFBFBD>locate<EFBFBD><EFBFBD>recover |
|
||||
| start| launch<EFBFBD><EFBFBD>create<EFBFBD><EFBFBD>begin<EFBFBD><EFBFBD>open|
|
||||
| make | create<EFBFBD><EFBFBD>set up<EFBFBD><EFBFBD>build<EFBFBD><EFBFBD>generate<EFBFBD><EFBFBD>compose<EFBFBD><EFBFBD>add<EFBFBD><EFBFBD>new |
|
||||
| send | deliver、dispatch、announce、distribute、route |
|
||||
| find | search、extract、locate、recover |
|
||||
| start| launch、create、begin、open|
|
||||
| make | create、set up、build、generate、compose、add、new |
|
||||
|
||||
ʹ<EFBFBD><EFBFBD> i<><69>j<EFBFBD><6A>k <20><>Ϊѭ<CEAA><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9>ڼ<DABC>user_i<EFBFBD><EFBFBD>member_i <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿɶ<EFBFBD><EFBFBD>Ի<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
使用 i、j、k 作为循环迭代器的名字过于简单,user_i、member_i 这种名字会更有表达力。因为循环层次越多,代码越难理解,有表达力的迭代器名字可读性会更高
|
||||
|
||||
Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴʵ<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>䳤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>
|
||||
为名字添加形容词等信息能让名字更具有表达力,但是名字也会变长。名字长短的准则是:作用域越大,名字越长。因此只有在短作用域才能使用一些简单名字。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>ܴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 名字不能带来歧义
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ˼<EFBFBD><EFBFBD>һ<EFBFBD>±<EFBFBD><EFBFBD>˻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кν<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD>塣
|
||||
起完名字要思考一下别人会对这个名字有何解读,会不会误解了原本想表达的含义。
|
||||
|
||||
<EFBFBD><EFBFBD> min<EFBFBD><EFBFBD>max <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> first<EFBFBD><EFBFBD>last <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ʿռ<EFBFBD><EFBFBD>İ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>begin<EFBFBD><EFBFBD>end <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>ʿռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ų<EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> end <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><CEB2><EFBFBD><EFBFBD>
|
||||
用 min、max 表示数量范围;用 first、last 表示访问空间的包含范围,begin、end 表示访问空间的排除范围,即 end 不包含尾部。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> is<EFBFBD><EFBFBD>can<EFBFBD><EFBFBD>should<EFBFBD><EFBFBD>has <EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>
|
||||
布尔相关的命名加上 is、can、should、has 等前缀。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>õĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 良好的代码风格
|
||||
|
||||
<EFBFBD>ʵ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>к<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
适当的空行和缩进。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ͣ<EFBFBD>
|
||||
排列整齐的注释:
|
||||
|
||||
```
|
||||
int a = 1; // ע<EFBFBD><EFBFBD>
|
||||
int b = 11; // ע<EFBFBD><EFBFBD>
|
||||
int c = 111; // ע<EFBFBD><EFBFBD>
|
||||
int a = 1; // 注释
|
||||
int b = 11; // 注释
|
||||
int c = 111; // 注释
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> html <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>ĸ<EFBFBD>ֵӦ<D6B5>úͱ<C3BA><CDB1><EFBFBD><EFBFBD><EFBFBD> html <20>е<EFBFBD>˳<EFBFBD><CBB3>һ<EFBFBD>£<EFBFBD>
|
||||
语句顺序不能随意,比如与 html 表单相关联的变量的赋值应该和表单在 html 中的顺序一致;
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>صĴ<EFBFBD><EFBFBD>밴<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
把相关的代码按块组织起来放在一起。
|
||||
|
||||
# <EFBFBD><EFBFBD>дע<EFBFBD><EFBFBD>
|
||||
# 编写注释
|
||||
|
||||
<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD>ע<EFBFBD>ע<EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>û̫<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ͻ<EFBFBD><EFBFBD>˷Ѵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䡣<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD>ֱ<EFBFBD>ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>벻<EFBFBD><EFBFBD>Ҫдע<EFBFBD>ͣ<EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪΪÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD> getter <EFBFBD><EFBFBD> setter <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>дע<EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD>Ը<EFBFBD><EFBFBD>
|
||||
阅读代码首先会注意到注释,如果注释没太大作用,那么就会浪费代码阅读的时间。那些能直接看出含义的代码不需要写注释,特别是并不需要为每个方法都加上注释,比如那些简单的 getter 和 setter 方法,为这些方法写注释反而让代码可读性更差。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ע<EFBFBD>;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD>дע<EFBFBD>͡<EFBFBD>
|
||||
不能因为有注释就随便起个名字,而是争取起个好名字而不写注释。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>취<EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD>߸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣
|
||||
可以用注释来记录采用当前解决办法的思考过程,从而让读者更容易理解代码。
|
||||
|
||||
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
注释用来提醒一些特殊情况。
|
||||
|
||||
<EFBFBD><EFBFBD> TODO <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>
|
||||
用 TODO 等做标记:
|
||||
|
||||
| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> | <20>÷<EFBFBD> |
|
||||
| 标记 | 用法 |
|
||||
|---|---|
|
||||
|TODO| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
|FIXME| <EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
|HACH| <EFBFBD>ֲڵĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
|XXX| Σ<EFBFBD>գ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> |
|
||||
|TODO| 待做 |
|
||||
|FIXME| 待修复 |
|
||||
|HACH| 粗糙的解决方案 |
|
||||
|XXX| 危险!这里有重要的问题 |
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>α<EFBFBD>дע<EFBFBD><EFBFBD>
|
||||
# 如何编写注释
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>
|
||||
尽量简洁明了:
|
||||
|
||||
```
|
||||
// The first String is student's name
|
||||
@ -97,7 +98,7 @@ Map<String, Integer> scoreMap = new HashMap<>();
|
||||
Map<String, Integer> scoreMap = new HashMap<>();
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
添加测试用例来说明:
|
||||
|
||||
```
|
||||
//...
|
||||
@ -107,7 +108,7 @@ int add(int x, int y) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD>ںܸ<EFBFBD><EFBFBD>ӵĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>
|
||||
在很复杂的函数调用中对每个参数标上名字:
|
||||
|
||||
```
|
||||
int a = 1;
|
||||
@ -115,37 +116,37 @@ int b = 2;
|
||||
int num = add(\* x = *\ a, \* y = *\ b);
|
||||
```
|
||||
|
||||
ʹ<EFBFBD><EFBFBD>רҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵĽ<EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣
|
||||
使用专业名词来缩短概念上的解释,比如用设计模式名来说明代码。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀɶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
# 提高控制流的可读性
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD>
|
||||
条件表达式中,左侧是变量,右侧是常数。比如下面第一个语句正确:
|
||||
|
||||
```
|
||||
if(len < 10)
|
||||
if(10 > len)
|
||||
```
|
||||
|
||||
if / else <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD> <20>ؼ<EFBFBD><D8BC><EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBC><EFBFBD>
|
||||
if / else 条件语句,逻辑的处理顺序为:① 正逻辑;② 关键逻辑;③ 简单逻辑。
|
||||
```
|
||||
if(a == b) {
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// 正逻辑
|
||||
} else{
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// 反逻辑
|
||||
}
|
||||
```
|
||||
|
||||
ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> ? : <20><>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>գ<EFBFBD><D5A3><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ò<EFBFBD><C3B2>ֳ<EFBFBD> if / else<EFBFBD><EFBFBD>
|
||||
只有在逻辑简单的情况下使用 ? : 三目运算符来使代码更紧凑,否则应该拆分成 if / else;
|
||||
|
||||
do / while <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD>棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD>Ի<EFBFBD><EFBFBD>ĵط<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> while <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>档
|
||||
do / while 的条件放在后面,不够简单明了,并且会有一些迷惑的地方,最好使用 while 来代替。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> goto Ŀ<>꣬<EFBFBD><EAA3AC>ô goto <20><><EFBFBD>һ<EFBFBD><D2BB>ܽ<EFBFBD><DCBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD>ǹ<EFBFBD><C7B9>ڸ<EFBFBD><DAB8>ӵ<EFBFBD> goto <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>Ӧ<EEA3AC>ñ<EFBFBD><C3B1><EFBFBD>ʹ<EFBFBD><CAB9> goto<EFBFBD><EFBFBD>
|
||||
如果只有一个 goto 目标,那么 goto 尚且还能接受,但是过于复杂的 goto 会让代码可读性特别差,应该避免使用 goto。
|
||||
|
||||
<EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD>һЩ return <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܼ<EFBFBD><DCBC><EFBFBD>Ƕ<EFBFBD>IJ<D7B5><C4B2><EFBFBD><EFBFBD><EFBFBD>
|
||||
在嵌套的循环中,用一些 return 语句往往能减少嵌套的层数。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
|
||||
# 拆分长表达式
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>Ŀɶ<EFBFBD><EFBFBD>Ժܲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
长表达式的可读性很差,可以引入一些解释变量从而拆分表达式:
|
||||
|
||||
```
|
||||
if line.split(':')[0].strip() == "root":
|
||||
@ -157,7 +158,7 @@ if username == "root":
|
||||
...
|
||||
```
|
||||
|
||||
ʹ<EFBFBD><EFBFBD>Ħ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
使用摩根定理简化一些逻辑表达式:
|
||||
|
||||
```
|
||||
if(!a && !b) {
|
||||
@ -170,9 +171,9 @@ if(a || b) {
|
||||
}
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
# 变量与可读性
|
||||
|
||||
**ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> break <EFBFBD><EFBFBD><EFBFBD><EFBFBD> return <EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ٿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD>
|
||||
**去除控制流变量**。在循环中通过使用 break 或者 return 可以减少控制流变量的使用。
|
||||
|
||||
```
|
||||
boolean done = false;
|
||||
@ -193,9 +194,9 @@ while(/* condition */) {
|
||||
}
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԽС<D4BD><D0A1>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õĵط<C4B5><D8B7><EFBFBD>
|
||||
**减小变量作用域**。作用域越小,越容易定位到变量所有使用的地方。
|
||||
|
||||
JavaScript <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñհ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> submit_form <20>Ǻ<EFBFBD><C7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>submitted <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ᱻ<EFBFBD>ύ<EFBFBD><E1BDBB><EFBFBD>Ρ<EFBFBD><CEA1><EFBFBD>һ<EFBFBD><D2BB>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD> submitted <20><>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>ʵ<EFBFBD>ְ<EFBFBD> submitted <20>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><CEA7>
|
||||
JavaScript 可以用闭包减小作用域。以下代码中 submit_form 是函数变量,submitted 变量控制函数不会被提交两次。第一个实现中 submitted 是全局变量,第二个实现把 submitted 放到匿名函数中,从而限制了起作用域范围。
|
||||
|
||||
```
|
||||
submitted = false;
|
||||
@ -216,16 +217,16 @@ var submit_form = (function() {
|
||||
}
|
||||
submitted = true;
|
||||
}
|
||||
}()); // () ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>
|
||||
}()); // () 使得外层匿名函数立即执行
|
||||
```
|
||||
|
||||
JavaScript <EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD> var <20><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> var <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
JavaScript 中没有用 var 声明的变量都是全局变量,而全局变量很容易造成迷惑,因此应当总是用 var 来声明变量。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
变量定义的位置应当离它使用的位置最近。
|
||||
|
||||
**ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**实例解析**
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶΣ<EFBFBD>
|
||||
在一个网页中有以下文本输入字段:
|
||||
|
||||
```
|
||||
<input type = "text" id = "input1" value = "a">
|
||||
@ -234,7 +235,7 @@ JavaScript
|
||||
<input type = "text" id = "input4" value = "d">
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD> input <20>ֶ<EFBFBD><D6B6>У<EFBFBD><D0A3><EFBFBD>ʼʵ<CABC><CAB5><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
现在要接受一个字符串并把它放到第一个空的 input 字段中,初始实现如下:
|
||||
|
||||
```
|
||||
var setFirstEmptyInput = function(new_alue) {
|
||||
@ -254,11 +255,11 @@ var setFirstEmptyInput = function(new_alue) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣺
|
||||
以上实现有以下问题:
|
||||
|
||||
- found <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- elem <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> for ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> while ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- found 可以去除;
|
||||
- elem 作用域过大;
|
||||
- 可以用 for 循环代替 while 循环;
|
||||
|
||||
```
|
||||
var setFirstEmptyInput = function(new_value) {
|
||||
@ -275,13 +276,13 @@ var setFirstEmptyInput = function(new_value) {
|
||||
};
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 抽取函数
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><EFBFBD><EFBFBD>ǰѴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
工程学就是把大问题拆分成小问题再把这些问题的解决方案放回一起。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ߲<EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>꣬Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>깤<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
首先应该明确一个函数的高层次目标,然后对于不是直接为了这个目标工作的代码,抽取出来放到独立的函数中。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԵĴ<EFBFBD><EFBFBD>룺
|
||||
介绍性的代码:
|
||||
|
||||
```
|
||||
int findClostElement(int[] arr) {
|
||||
@ -302,7 +303,7 @@ int findClostElement(int[] arr) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD>ⲿ<EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>꣬<EFBFBD>߲<EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺô<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD>ԡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
以上代码中循环部分主要计算距离,这部分不属于代码高层次目标,高层次目标是寻找最小距离的值,因此可以把这部分代替提取到独立的函数中。这样做也带来一个额外的好处有:可以单独进行测试、可以快速找到程序错误并修改。
|
||||
|
||||
```
|
||||
public int findClostElement(int[] arr) {
|
||||
@ -319,22 +320,22 @@ public int findClostElement(int[] arr) {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>Խ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫȥ<EFBFBD>˽<EFBFBD>ijһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڶ<EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>Ӻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻõġ<EFBFBD>
|
||||
并不是函数抽取的越多越好,如果抽取过多,在阅读代码的时候可能需要不断跳来跳去。只有在当前函数不需要去了解某一块代码细节而能够表达其内容时,把这块代码抽取成子函数才是好的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡҲ<EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ
|
||||
函数抽取也用于减小代码的冗余。
|
||||
|
||||
# һ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 一次只做一件事
|
||||
|
||||
ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>µĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
只做一件事的代码很容易让人知道其要做的事;
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD>г<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD>ͬ<EFBFBD>Ķ<EFBFBD><EFBFBD>䡣
|
||||
基本流程:列出代码所做的所有任务;把每个任务拆分到不同的函数,或者不同的段落。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 用自然语言表述代码
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>α<EFBFBD><EFBFBD><EFBFBD>룬Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
先用自然语言书写代码逻辑,也就是伪代码,然后再写代码,这样代码逻辑会更清晰。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 减少代码量
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̻<EFBFBD><EFBFBD>кܶ<EFBFBD><EFBFBD>仯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õġ<EFBFBD>
|
||||
不要过度设计,编码过程会有很多变化,过度设计的内容到最后往往是无用的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֡<EFBFBD>
|
||||
多用标准库实现。
|
||||
|
File diff suppressed because it is too large
Load Diff
733
notes/算法.md
733
notes/算法.md
File diff suppressed because it is too large
Load Diff
657
notes/计算机操作系统.md
657
notes/计算机操作系统.md
@ -1,248 +1,249 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>](#<23><>һ<EFBFBD><D2BB>-<2D><><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#2-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4. <EFBFBD>첽](#4-<EFBFBD>첽)
|
||||
* [ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD>жϷ<EFBFBD><EFBFBD><EFBFBD>](#<23>жϷ<D0B6><CFB7><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>)
|
||||
* [2. <EFBFBD>쳣](#2-<EFBFBD>쳣)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>ں˺<EFBFBD><EFBFBD>ں<EFBFBD>](#<23><><EFBFBD>ں˺<DABA><EFBFBD>ں<EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD>)
|
||||
* [2. <EFBFBD>ں<EFBFBD>](#2-<EFBFBD>ں<EFBFBD>)
|
||||
* [<EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̹<EFBFBD><CCB9><EFBFBD>](#<23>ڶ<EFBFBD><DAB6><EFBFBD>-<2D><><EFBFBD>̹<EFBFBD><CCB9><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD>߳<EFBFBD>](#2-<EFBFBD>߳<EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>](#<23><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD>л<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨](#<23><><EFBFBD><EFBFBD><EFBFBD>㷨)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>еĵ<EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>)
|
||||
* [1.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD>](#11-<2D><><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>)
|
||||
* [1.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#12-<2D><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>)
|
||||
* [1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#13-<2D><><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽϵͳ<EFBFBD>еĵ<EFBFBD><EFBFBD><EFBFBD>](#2-<2D><><EFBFBD><EFBFBD>ʽϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>)
|
||||
* [2.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#21-<2D><><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>)
|
||||
* [2.2 ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>ת](#22-ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>ת)
|
||||
* [2.3 <EFBFBD>༶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#23-<2D>༶<EFBFBD><E0BCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2.4 <EFBFBD>̽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#24-<2D>̽<EFBFBD><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. ʵʱϵͳ<EFBFBD>еĵ<EFBFBD><EFBFBD><EFBFBD>](#3-ʵʱϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>)
|
||||
* [1. <EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>](#1-<EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. ͬ<EFBFBD><EFBFBD><EFBFBD>뻥<EFBFBD><EFBFBD>](#2-ͬ<><CDAC><EFBFBD>뻥<EFBFBD><EBBBA5>)
|
||||
* [3. <EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>](#3-<EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4. <EFBFBD>ܳ<EFBFBD>](#4-<EFBFBD>ܳ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>)
|
||||
* [1. <EFBFBD>ܵ<EFBFBD>](#1-<EFBFBD>ܵ<EFBFBD>)
|
||||
* [2. <EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>](#2-<EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<2D><>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>)
|
||||
* [4. <EFBFBD>ź<EFBFBD>](#4-<EFBFBD>ź<EFBFBD>)
|
||||
* [5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>](#5-<2D><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>)
|
||||
* [6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#6-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD>-д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD>ѧ<EFBFBD>ҽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#2-<2D><>ѧ<EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD>](#2-<2D><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4>)
|
||||
* [2.1 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#21-<2D>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2.2 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#22-<2D>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EBB1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [2.3 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#23-<2D>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD>)
|
||||
* [2.4 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ȴ<EFBFBD>](#24-<2D>ƻ<EFBFBD><C6BB><EFBFBD>·<EFBFBD>ȴ<EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [3.1 <EFBFBD><EFBFBD>ȫ״̬](#31-<EFBFBD><EFBFBD>ȫ״̬)
|
||||
* [3.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>㷨](#32-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>㷨)
|
||||
* [3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>㷨](#33-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC>㷨)
|
||||
* [4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>](#4-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>)
|
||||
* [4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨](#41-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨)
|
||||
* [4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>](#42-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>](#<23><>ҳ<EFBFBD><D2B3><EFBFBD>ֶ<EFBFBD>)
|
||||
* [1. <EFBFBD><EFBFBD>ҳ](#1-<EFBFBD><EFBFBD>ҳ)
|
||||
* [2. <EFBFBD>ֶ<EFBFBD>](#2-<EFBFBD>ֶ<EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD>ҳʽ](#3-<EFBFBD><EFBFBD>ҳʽ)
|
||||
* [4. <EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#4-<2D><>ҳ<EFBFBD><D2B3><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [ҳ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>㷨](#ҳ<><D2B3><EFBFBD>û<EFBFBD><C3BB>㷨)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD>ѣ<EFBFBD>Optimal<EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>optimal)
|
||||
* [2. <EFBFBD>Ƚ<EFBFBD><EFBFBD>ȳ<EFBFBD><EFBFBD><EFBFBD>FIFO<EFBFBD><EFBFBD>](#2-<EFBFBD>Ƚ<EFBFBD><EFBFBD>ȳ<EFBFBD>fifo)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δʹ<EFBFBD>ã<EFBFBD>LRU, Least Recently Used<EFBFBD><EFBFBD>](#3-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δʹ<EFBFBD><EFBFBD>lru,-least-recently-used)
|
||||
* [4. ʱ<EFBFBD>ӣ<EFBFBD>Clock<EFBFBD><EFBFBD>](#4-ʱ<EFBFBD><EFBFBD>clock)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD>](#<23><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨](#<23><><EFBFBD>̵<EFBFBD><CCB5><EFBFBD><EFBFBD>㷨)
|
||||
* [1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FCFS, First Come First Serverd<EFBFBD><EFBFBD>](#1-<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD>fcfs,-first-come-first-serverd)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>SSTF, Shortest Seek Time First<EFBFBD><EFBFBD>](#2-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>sstf,-shortest-seek-time-first)
|
||||
* [3. ɨ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>SCAN<EFBFBD><EFBFBD>](#3-ɨ<EFBFBD><EFBFBD><EFBFBD>㷨scan)
|
||||
* [4. ѭ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>CSCAN<EFBFBD><EFBFBD>](#4-ѭ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>㷨cscan)
|
||||
* [<EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [第一章 概述](#第一章-概述)
|
||||
* [操作系统基本特征](#操作系统基本特征)
|
||||
* [1. 并发](#1-并发)
|
||||
* [2. 共享](#2-共享)
|
||||
* [3. 虚拟](#3-虚拟)
|
||||
* [4. 异步](#4-异步)
|
||||
* [系统调用](#系统调用)
|
||||
* [中断分类](#中断分类)
|
||||
* [1. 外中断](#1-外中断)
|
||||
* [2. 异常](#2-异常)
|
||||
* [3. 陷入](#3-陷入)
|
||||
* [大内核和微内核](#大内核和微内核)
|
||||
* [1. 大内核](#1-大内核)
|
||||
* [2. 微内核](#2-微内核)
|
||||
* [第二章 进程管理](#第二章-进程管理)
|
||||
* [进程与线程](#进程与线程)
|
||||
* [1. 进程](#1-进程)
|
||||
* [2. 线程](#2-线程)
|
||||
* [3. 区别](#3-区别)
|
||||
* [进程状态的切换](#进程状态的切换)
|
||||
* [调度算法](#调度算法)
|
||||
* [1. 批处理系统中的调度](#1-批处理系统中的调度)
|
||||
* [1.1 先来先服务](#11-先来先服务)
|
||||
* [1.2 短作业优先](#12-短作业优先)
|
||||
* [1.3 最短剩余时间优先](#13-最短剩余时间优先)
|
||||
* [2. 交互式系统中的调度](#2-交互式系统中的调度)
|
||||
* [2.1 优先权优先](#21-优先权优先)
|
||||
* [2.2 时间片轮转](#22-时间片轮转)
|
||||
* [2.3 多级反馈队列](#23-多级反馈队列)
|
||||
* [2.4 短进程优先](#24-短进程优先)
|
||||
* [3. 实时系统中的调度](#3-实时系统中的调度)
|
||||
* [进程同步](#进程同步)
|
||||
* [1. 临界区](#1-临界区)
|
||||
* [2. 同步与互斥](#2-同步与互斥)
|
||||
* [3. 信号量](#3-信号量)
|
||||
* [4. 管程](#4-管程)
|
||||
* [进程通信](#进程通信)
|
||||
* [1. 管道](#1-管道)
|
||||
* [2. 信号量](#2-信号量)
|
||||
* [3. 消息队列](#3-消息队列)
|
||||
* [4. 信号](#4-信号)
|
||||
* [5. 共享内存](#5-共享内存)
|
||||
* [6. 套接字](#6-套接字)
|
||||
* [经典同步问题](#经典同步问题)
|
||||
* [1. 读者-写者问题](#1-读者-写者问题)
|
||||
* [2. 哲学家进餐问题](#2-哲学家进餐问题)
|
||||
* [第三章 死锁](#第三章-死锁)
|
||||
* [死锁的条件](#死锁的条件)
|
||||
* [死锁的处理方法](#死锁的处理方法)
|
||||
* [1. 鸵鸟策略](#1-鸵鸟策略)
|
||||
* [2. 死锁预防](#2-死锁预防)
|
||||
* [2.1 破坏互斥条件](#21-破坏互斥条件)
|
||||
* [2.2 破坏请求与保持条件](#22-破坏请求与保持条件)
|
||||
* [2.3 破坏不可抢占条件](#23-破坏不可抢占条件)
|
||||
* [2.4 破坏环路等待](#24-破坏环路等待)
|
||||
* [3. 死锁避免](#3-死锁避免)
|
||||
* [3.1 安全状态](#31-安全状态)
|
||||
* [3.2 单个资源的银行家算法](#32-单个资源的银行家算法)
|
||||
* [3.3 多个资源的银行家算法](#33-多个资源的银行家算法)
|
||||
* [4. 死锁检测与死锁恢复](#4-死锁检测与死锁恢复)
|
||||
* [4.1 死锁检测算法](#41-死锁检测算法)
|
||||
* [4.2 死锁恢复](#42-死锁恢复)
|
||||
* [第四章 存储器管理](#第四章-存储器管理)
|
||||
* [虚拟内存](#虚拟内存)
|
||||
* [分页与分段](#分页与分段)
|
||||
* [1. 分页](#1-分页)
|
||||
* [2. 分段](#2-分段)
|
||||
* [3. 段页式](#3-段页式)
|
||||
* [4. 分页与分段区别](#4-分页与分段区别)
|
||||
* [页面置换算法](#页面置换算法)
|
||||
* [1. 最佳(Optimal)](#1-最佳optimal)
|
||||
* [2. 先进先出(FIFO)](#2-先进先出fifo)
|
||||
* [3. 最近最久未使用(LRU, Least Recently Used)](#3-最近最久未使用lru,-least-recently-used)
|
||||
* [4. 时钟(Clock)](#4-时钟clock)
|
||||
* [第五章 设备管理](#第五章-设备管理)
|
||||
* [磁盘调度算法](#磁盘调度算法)
|
||||
* [1. 先来先服务(FCFS, First Come First Serverd)](#1-先来先服务fcfs,-first-come-first-serverd)
|
||||
* [2. 最短寻道时间优先(SSTF, Shortest Seek Time First)](#2-最短寻道时间优先sstf,-shortest-seek-time-first)
|
||||
* [3. 扫描算法(SCAN)](#3-扫描算法scan)
|
||||
* [4. 循环扫描算法(CSCAN)](#4-循环扫描算法cscan)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><>һ<EFBFBD><D2BB> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
## <20><><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 第一章 概述
|
||||
|
||||
### 1. <20><><EFBFBD><EFBFBD>
|
||||
## 操作系统基本特征
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָͬһʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>
|
||||
### 1. 并发
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪӲ<EFBFBD><EFBFBD>֧<EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD>߶ദ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
并发性是指宏观上在一段时间内能同时运行多个程序,而并行性则指同一时刻能运行多个指令。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺<EFBFBD><EFBFBD>̣߳<EFBFBD>ʹ<EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
并行需要硬件支持,如多流水线或者多处理器。
|
||||
|
||||
### 2. <20><><EFBFBD><EFBFBD>
|
||||
操作系统通过引入进程和线程,使得程序能够并发运行。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָϵͳ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̹<EFBFBD>ͬʹ<EFBFBD>á<EFBFBD>
|
||||
### 2. 共享
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
共享是指系统中的资源可以供多个并发进程共同使用。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>Ϊ<EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD>ͬһʱ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֶ<EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ķ<EFBFBD><EFBFBD>ʡ<EFBFBD>
|
||||
有两种共享方式:互斥共享和同时共享。
|
||||
|
||||
### 3. <20><><EFBFBD><EFBFBD>
|
||||
互斥共享的资源称为临界资源,例如打印机等,在同一时间只允许一个进程访问,否则会出现错误,需要用同步机制来实现对临界资源的访问。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>⼼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>塣<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⼼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ָ<EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳշָ<EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ָ<EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD>ִֻ<EFBFBD><EFBFBD>һС<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3. 虚拟
|
||||
|
||||
### 4. <20>첽
|
||||
虚拟技术把一个物理实体转换为多个逻辑实体。主要有两种虚拟技术:时分复用技术和空分复用技术,例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。
|
||||
|
||||
<EFBFBD>첽<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>̲<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣͣ<EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4. 异步
|
||||
|
||||
## ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>
|
||||
异步是指进程不是一次性执行完毕,而是走走停停,以不可知的速度向前推进。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>̬<EFBFBD><EFBFBD>Ҫ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD>ôӶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ںˣ<EFBFBD><EFBFBD>ɲ<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>
|
||||
## 系统调用
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̹<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
如果一个进程在用户态需要用到操作系统的一些功能,就需要使用系统调用从而陷入内核,由操作系统代为完成。
|
||||
|
||||
## <20>жϷ<D0B6><CFB7><EFBFBD>
|
||||
可以由系统调用请求的功能有设备管理、文件管理、进程管理、进程通信、存储器管理等。
|
||||
|
||||
### 1. <20><><EFBFBD>ж<EFBFBD>
|
||||
## 中断分类
|
||||
|
||||
<EFBFBD><EFBFBD> CPU ִ<><D6B4>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> I/O <20><><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6><CFA3><EFBFBD>ʾ<EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3A1A3B4><EFBFBD><E2BBB9>ʱ<EFBFBD><CAB1><EFBFBD>жϡ<D0B6><CFA1><EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD>жϵȡ<CFB5>
|
||||
### 1. 外中断
|
||||
|
||||
### 2. <20>쳣
|
||||
由 CPU 执行指令以外的事件引起,如 I/O 结束中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输入/输出请求。此外还有时钟中断、控制台中断等。
|
||||
|
||||
<EFBFBD><EFBFBD> CPU ִ<><D6B4>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롢<EFBFBD><EBA1A2>ַԽ<D6B7>硢<EFBFBD><E7A1A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
### 2. 异常
|
||||
|
||||
### 3. <20><><EFBFBD><EFBFBD>
|
||||
由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD>á<EFBFBD>
|
||||
### 3. 陷入
|
||||
|
||||
## <20><><EFBFBD>ں˺<DABA><EFBFBD>ں<EFBFBD>
|
||||
在用户程序中使用系统调用。
|
||||
|
||||
### 1. <20><><EFBFBD>ں<EFBFBD>
|
||||
## 大内核和微内核
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܽ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>ںˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>ģ<EFBFBD>鹲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܸߵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
### 1. 大内核
|
||||
|
||||
### 2. <>ں<EFBFBD>
|
||||
大内核是将操作系统功能作为一个紧密结合的整体放到内核,由于各模块共享信息,因此有很高的性能。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><EFBFBD>ںˣ<EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں˵ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD><EFBFBD>Ƴ<EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>ݷֲ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪƵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>̬<EFBFBD>ͺ<EFBFBD><EFBFBD><EFBFBD>̬֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>
|
||||
### 2. 微内核
|
||||
|
||||
# <20>ڶ<EFBFBD><DAB6><EFBFBD> <20><><EFBFBD>̹<EFBFBD><CCB9><EFBFBD>
|
||||
由于操作系统不断复杂,因此将一部分操作系统功能移出内核,从而降低内核的复杂性。移出的部分根据分层的原则划分成若干服务,相互独立。但是需要频繁地在用户态和核心态之间进行切换,会有一定的性能损失。
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
|
||||
# 第二章 进程管理
|
||||
|
||||
### 1. <20><><EFBFBD><EFBFBD>
|
||||
## 进程与线程
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
|
||||
### 1. 进程
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>̿<EFBFBD><EFBFBD>ƿ<EFBFBD> (Process Control Block, PCB) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵Ļ<CCB5><C4BB><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ν<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺ͳ<CCBA><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> PCB <20>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD>
|
||||
进程是操作系统进行资源分配的基本单位。
|
||||
|
||||
### 2. <20>߳<EFBFBD>
|
||||
进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣߳<EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵĻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>
|
||||
### 2. 线程
|
||||
|
||||
### 3. <20><><EFBFBD><EFBFBD>
|
||||
一个进程中可以有多个线程,线程是独立调度的基本单位。同一个进程中的多个线程之间可以并发执行,它们共享进程资源。
|
||||
|
||||
- ӵ<><D3B5><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̲߳<DFB3>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>߳̿<DFB3><CCBF>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><CCB5><EFBFBD>Դ<EFBFBD><D4B4>
|
||||
### 3. 区别
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵĻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD>̵߳<EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>߳<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>
|
||||
- 拥有资源:进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问率属进程的资源。
|
||||
|
||||
- ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>ҪΪ֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ䡢I/O <20>豸<EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD>˲<EFBFBD><CBB2><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ʱ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶأ<C6B5><D8A3>ڽ<EFBFBD><DABD>н<EFBFBD><D0BD><EFBFBD><EFBFBD>л<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>漰<EFBFBD><E6BCB0>ǰִ<C7B0>н<EFBFBD><D0BD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>漰<EFBFBD>µ<EFBFBD><C2B5>Ƚ<EFBFBD><C8BD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD><C3A1><EFBFBD><EFBFBD>߳<EFBFBD><DFB3>л<EFBFBD>ʱֻ<CAB1>豣<EFBFBD><E8B1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>
|
||||
- 调度:线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。
|
||||
|
||||
- ͨ<EFBFBD>ŷ<EFBFBD><EFBFBD>棺<EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD>ͨ<EFBFBD><EFBFBD> (IPC) <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD>ֶεĸ<CEB5><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>֤<EFBFBD><D6A4><EFBFBD>ݵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD>̼߳<DFB3><CCBC><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>ֱ<EFBFBD>Ӷ<EFBFBD>/дͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ݶΣ<DDB6><CEA3><EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
|
||||
- 系统开销:由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,因此操作系统所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置。而线程切换时只需保存和设置少量寄存器内容,开销很小。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>QQ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܶ<D0BA><DCB6>̣߳<DFB3><CCA3><EFBFBD><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD><EFBFBD>̡߳<DFB3><CCA1>¼<EFBFBD><C2BC><EFBFBD>Ӧ<EFBFBD>̡߳<DFB3><CCA1><EFBFBD>Ⱦ<EFBFBD>̵߳ȵȣ<C8B5><C8A3>̵߳IJ<CCB5><C4B2><EFBFBD>ִ<EFBFBD><D6B4>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӴӶ<D3B4><D3B6><EFBFBD><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD>
|
||||
- 通信方面:进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。
|
||||
|
||||
## <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD>л<EFBFBD>
|
||||
举例:QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。
|
||||
|
||||

|
||||
## 进程状态的切换
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU<50><55>ȱ<EFBFBD><C8B1> CPU <20><><EFBFBD>ý<EFBFBD><C3BD>̴<EFBFBD><CCB4><EFBFBD><EFBFBD><EFBFBD>̬ת<CCAC><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>
|
||||

|
||||
|
||||
ֻ<EFBFBD>о<EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU ʱ<>䣬תΪ<D7AA><CEAA><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4>Ľ<EFBFBD><C4BD>̣<EFBFBD><CCA3>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU ʱ<><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>ͻ<EFBFBD>תΪ<D7AA><CEAA><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD>һ<EFBFBD>ε<EFBFBD><CEB5>ȡ<EFBFBD>
|
||||
阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU,缺少 CPU 会让进程从运行态转换为就绪态。
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
|
||||
|
||||
<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>
|
||||
## 调度算法
|
||||
|
||||
### 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>
|
||||
需要针对不同环境来讨论调度算法。
|
||||
|
||||
#### 1.1 <20><><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>
|
||||
### 1. 批处理系统中的调度
|
||||
|
||||
first-come first-serverd<72><64>FCFS<46><53><EFBFBD><EFBFBD>
|
||||
#### 1.1 先来先服务
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>
|
||||
first-come first-serverd(FCFS)。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱ<EFBFBD>ȴ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD>ҵִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫִ<EFBFBD>кܳ<EFBFBD>ʱ<EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD>ȴ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
调度最先进入就绪队列的作业。
|
||||
|
||||
#### 1.2 <20><><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>
|
||||
有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
|
||||
|
||||
shortest job first<73><74>SJF<4A><46><EFBFBD><EFBFBD>
|
||||
#### 1.2 短作业优先
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ȹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>
|
||||
shortest job first(SJF)。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD>п<EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>Զ<EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
调度估计运行时间最短的作业。
|
||||
|
||||
#### 1.3 <20><><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
长作业有可能会饿死,处于一直等待短作业执行完毕的状态。如果一直有短作业到来,那么长作业永远得不到调度。
|
||||
|
||||
shortest remaining time next<78><74>SRTN<54><4E><EFBFBD><EFBFBD>
|
||||
#### 1.3 最短剩余时间优先
|
||||
|
||||
### 2. <20><><EFBFBD><EFBFBD>ʽϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>
|
||||
shortest remaining time next(SRTN)。
|
||||
|
||||
#### 2.1 <20><><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>
|
||||
### 2. 交互式系统中的调度
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ֮<EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>ȷ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>
|
||||
#### 2.1 优先权优先
|
||||
|
||||
<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD> = (<28>ȴ<EFBFBD>ʱ<EFBFBD><CAB1> + Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>) / Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1> = <20><>Ӧʱ<D3A6><CAB1> / Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
||||
除了可以手动赋予优先权之外,还可以把响应比作为优先权,这种调度方式叫做高响应比优先调度算法。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϊ<EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD> SJF <20>г<EFBFBD><D0B3><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣬<EFBFBD><E2A3AC>Ϊ<EFBFBD><CEAA><EFBFBD>ŵȴ<C5B5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>Ҳ<EFBFBD><D2B2>Խ<EFBFBD><D4BD>Խ<EFBFBD>ߡ<EFBFBD>
|
||||
响应比 = (等待时间 + 要求服务时间) / 要求服务时间 = 响应时间 / 要求服务时间
|
||||
|
||||
#### 2.2 ʱ<><CAB1>Ƭ<EFBFBD><C6AC>ת
|
||||
这种调度算法主要是为了解决 SJF 中长作业可能会饿死的问题,因为随着等待时间的增长,响应比也会越来越高。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD> FCFS <20><>ԭ<EFBFBD><D4AD><EFBFBD>ų<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ÿ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BD>̣<EFBFBD><CCA3>ý<EFBFBD><C3BD>̿<EFBFBD><CCBF><EFBFBD>ִ<EFBFBD><D6B4>һ<EFBFBD><D2BB>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ɼ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>жϣ<D0B6><CFA3><EFBFBD><EFBFBD>ȳ<EFBFBD><C8B3><EFBFBD><EFBFBD><EFBFBD>ֹͣ<CDA3>ý<EFBFBD><C3BD>̵<EFBFBD>ִ<EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ĩβ<C4A9><CEB2>ͬʱ<CDAC><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CPU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<D7B5><C4BD>̡<EFBFBD>
|
||||
#### 2.2 时间片轮转
|
||||
|
||||
ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>ת<EFBFBD>㷨<EFBFBD><EFBFBD>Ч<EFBFBD>ʺ<EFBFBD>ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD>Ĵ<EFBFBD>С<EFBFBD>кܴ<EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊÿ<EFBFBD>ν<EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ƭ̫С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>̫Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><EFBFBD>ϾͻỨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䡣
|
||||
将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 分配给队首的进程。
|
||||
|
||||
#### 2.3 <20>༶<EFBFBD><E0BCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
时间片轮转算法的效率和时间片的大小有很大关系。因为每次进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,进程切换太频繁,在进程切换上就会花过多时间。
|
||||
|
||||

|
||||
#### 2.3 多级反馈队列
|
||||
|
||||
1. <20><><EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8>費ͬ<E8B2BB><CDAC><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>ߣ<EFBFBD><DFA3>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD><CDA1><EFBFBD><EFBFBD>㷨<EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD>Ĵ<EFBFBD>СҲ<D0A1><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȨԽ<C8A8>ߵĶ<DFB5><C4B6><EFBFBD><EFBFBD>У<EFBFBD>Ϊÿ<CEAA><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>涨<EFBFBD><E6B6A8>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC>ԽС<D4BD><D0A1>
|
||||

|
||||
|
||||
2. <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ĩβ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> FCFS ԭ<><D4AD><EFBFBD>Ŷӵȴ<D3B5><C8B4><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ý<EFBFBD><C3BD><EFBFBD>ִ<EFBFBD><D6B4>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ʱ<EFBFBD><CAB1>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>δ<EFBFBD><CEB4><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD><EFBFBD>ȳ<EFBFBD><C8B3><EFBFBD><EFBFBD>㽫<EFBFBD>ý<EFBFBD><C3BD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>еĶ<D0B5>β<EFBFBD><CEB2>
|
||||
1. 设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权越高的队列中,为每个进程所规定的执行时间片就越小。
|
||||
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ i -1 <20><><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD><D0BE><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ż<EFBFBD><C5BB><EFBFBD><EFBFBD>ȵ<EFBFBD> i <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĽ<D0B5><C4BD>̡<EFBFBD>
|
||||
2. 当一个新进程进入内存后,首先将它放入第一队列的末尾,按 FCFS 原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入下一个队列的队尾。
|
||||
|
||||
<EFBFBD>ŵ㣺ʵʱ<EFBFBD>Ժã<EFBFBD>ͬʱ<EFBFBD>ʺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>
|
||||
3. 仅当前 i -1 个队列均空时,才会调度第 i 个队列中的进程。
|
||||
|
||||
#### 2.4 <20>̽<EFBFBD><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
优点:实时性好,同时适合运行短作业和长作业。
|
||||
|
||||
### 3. ʵʱϵͳ<CFB5>еĵ<D0B5><C4B5><EFBFBD>
|
||||
#### 2.4 短进程优先
|
||||
|
||||
ʵʱϵͳҪһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ڵõ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>
|
||||
### 3. 实时系统中的调度
|
||||
|
||||
<EFBFBD><EFBFBD>ΪӲʵʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵʱ<EFBFBD><EFBFBD>ǰ<EFBFBD>߱<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԵĽ<EFBFBD>ֹʱ<EFBFBD>䣬<EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ʱ<EFBFBD><EFBFBD>
|
||||
实时系统要一个服务请求在一个确定时间内得到响应。
|
||||
|
||||
## <20><><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>
|
||||
分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
|
||||
|
||||
### 1. <20>ٽ<EFBFBD><D9BD><EFBFBD>
|
||||
## 进程同步
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>Ƕδ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1. 临界区
|
||||
|
||||
Ϊ<EFBFBD>˻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ƚ<EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>顣
|
||||
对临界资源进行访问的那段代码称为临界区。
|
||||
|
||||
为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
|
||||
|
||||
```html
|
||||
// entry section
|
||||
@ -250,44 +251,44 @@ shortest remaining time next
|
||||
// exit section
|
||||
```
|
||||
|
||||
### 2. ͬ<EFBFBD><EFBFBD><EFBFBD>뻥<EFBFBD><EFBFBD>
|
||||
### 2. 同步与互斥
|
||||
|
||||
ͬ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD>һ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬһʱ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
同步指多个进程按一定顺序执行;互斥指多个进程在同一时刻只有一个进程能进入临界区。
|
||||
|
||||
ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵĻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵġ<EFBFBD>
|
||||
同步是在对临界区互斥访问的基础上,通过其它机制来实现有序访问的。
|
||||
|
||||
### 3. <EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3. 信号量
|
||||
|
||||
**<EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Samaphore<EFBFBD><EFBFBD>** <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><CDB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ִ<EFBFBD><D6B4> down <EFBFBD><EFBFBD> up <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> P <EFBFBD><EFBFBD> V <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
**信号量(Samaphore)** 是一个整型变量,可以对其执行 down 和 up 操作,也就是常见的 P 和 V 操作。
|
||||
|
||||
- **down** : <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 <20><>ִ<EFBFBD><D6B4> -1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><C5BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˯<EFBFBD>ߣ<EFBFBD><DFA3>ȴ<EFBFBD><C8B4>ź<EFBFBD><C5BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0<><30>
|
||||
- **up**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> +1 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>˯<EFBFBD>ߵĽ<DFB5><C4BD>̣<EFBFBD><CCA3>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> down <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- **down** : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,将进程睡眠,等待信号量大于 0;
|
||||
- **up**:对信号量执行 +1 操作,并且唤醒睡眠的进程,让进程完成 down 操作。
|
||||
|
||||
down <EFBFBD><EFBFBD> up <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɷָͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>жϡ<EFBFBD>
|
||||
down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡֵֻ<EFBFBD><EFBFBD>Ϊ 0 <20><><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD>ô<EFBFBD>ͳ<EFBFBD>Ϊ<EFBFBD><CEAA>**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Mutex<65><78>**<2A><>0 <20><>ʾ<EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1 <20><>ʾ<EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
如果信号量的取值只能为 0 或者 1,那么就成为了**互斥量(Mutex)**,0 表示临界区已经加锁,1 表示临界区解锁。
|
||||
|
||||
```c
|
||||
typedef int samaphore;
|
||||
samaphore mutex = 1;
|
||||
void P1() {
|
||||
down(mutex);
|
||||
// <EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
// 临界区
|
||||
up(mutex);
|
||||
}
|
||||
|
||||
void P2() {
|
||||
down(mutex);
|
||||
// <EFBFBD>ٽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
// 临界区
|
||||
up(mutex);
|
||||
}
|
||||
```
|
||||
|
||||
**ʹ<EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**使用信号量实现生产者-消费者问题**
|
||||
|
||||
ʹ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> mutex <20><><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>з<EFBFBD><D0B7>ʣ<EFBFBD>empty <20><>¼<EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>full <20><>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
使用一个互斥量 mutex 来对临界资源进行访问;empty 记录空缓冲区的数量,full 记录满缓冲区的数量。
|
||||
|
||||
ע<EFBFBD>⣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> down <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȶ<EFBFBD><C8B6>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4> down <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4> down(empty) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> empty = 0<><30><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˯<EFBFBD>ߡ<EFBFBD><DFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ܽ<EFBFBD><DCBD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4> up(empty) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߾ͻ<DFBE>һֱ<D2BB>ȴ<EFBFBD><C8B4><EFBFBD>ȥ<EFBFBD><C8A5>
|
||||
注意,必须先执行 down 操作再用互斥量对临界区加锁,否则会出现死锁。因为如果都先对临界区加锁,然后再执行 down 操作,那么可能会出现这种情况:生产者对临界区加锁后,执行 down(empty) 操作,发现 empty = 0,此时生成者睡眠。消费者此时不能进入临界区,因为生产者对临界区加锁了,也就无法执行 up(empty) 操作,那么生产者和消费者就会一直等待下去。
|
||||
|
||||
```c
|
||||
#define N 100
|
||||
@ -319,11 +320,11 @@ void consumer() {
|
||||
}
|
||||
```
|
||||
|
||||
### 4. <EFBFBD>ܳ<EFBFBD>
|
||||
### 4. 管程
|
||||
|
||||
ʹ<EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̰ܳѿ<EFBFBD><EFBFBD>ƵĴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳʹ<EFBFBD>ÿͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ס<EFBFBD>
|
||||
使用信号量机制实现的生产者消费者问题需要客户端代码做很多控制,而管程把控制的代码独立出来,不仅不容易出错,也使得客户端代码调用更容易。
|
||||
|
||||
c <EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>֧<EFBFBD>ֹ̣ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pascal <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡ܳ<DCB3>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĹܳ<C4B9><DCB3>ṩ<EFBFBD><E1B9A9> insert() <EFBFBD><EFBFBD> remove() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣
|
||||
c 语言不支持管程,下面的示例代码使用了类 Pascal 语言来描述管程。示例代码中的管程提供了 insert() 和 remove() 方法,客户端代码通过调用这两个方法来解决生产者-消费者问题。
|
||||
|
||||
```pascal
|
||||
monitor ProducerConsumer
|
||||
@ -342,11 +343,11 @@ monitor ProducerConsumer
|
||||
end monitor;
|
||||
```
|
||||
|
||||
<EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ù̡ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һֱռ<EFBFBD>ụ̀ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ù̡ܳ<EFBFBD>
|
||||
管程有一个重要特性:在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否者其它进程永远不能使用管程。
|
||||
|
||||
<EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>صIJ<D8B5><C4B2><EFBFBD><EFBFBD><EFBFBD>**wait()** <EFBFBD><EFBFBD> **signal()** <EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD> wait() <20><><EFBFBD><EFBFBD><EFBFBD>ᵼ<EFBFBD>µ<EFBFBD><C2B5>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹܳ<D1B9><DCB3>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>̳<EFBFBD><CCB3>С<EFBFBD>signal() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڻ<EFBFBD><DABB>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD>̡<EFBFBD>
|
||||
管程引入了 **条件变量** 以及相关的操作:**wait()** 和 **signal()** 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来让另一个进程持有。signal() 操作用于唤醒被阻塞的进程。
|
||||
|
||||
**ʹ<EFBFBD>ùܳ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**使用管程实现生成者-消费者问题**
|
||||
|
||||
```pascal
|
||||
monitor ProducerConsumer
|
||||
@ -390,53 +391,53 @@ begin
|
||||
end;
|
||||
```
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>
|
||||
## 进程通信
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ſ<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>ͨ<EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵߳<EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||||
进程通信可以看成是不同进程间的线程通信,对于同一个进程内线程的通信方式,主要使用信号量、条件变量等同步机制。
|
||||
|
||||
### 1. <EFBFBD>ܵ<EFBFBD>
|
||||
### 1. 管道
|
||||
|
||||
<EFBFBD>ܵ<EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD>ȳ<EFBFBD><EFBFBD>ġ<EFBFBD><EFBFBD>ṹ<EFBFBD>ġ<EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹܵ<EFBFBD><EFBFBD><EFBFBD>β<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӹܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD>ݡ<EFBFBD>
|
||||
管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。
|
||||
|
||||
<EFBFBD>ܵ<EFBFBD><EFBFBD>ṩ<EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>չܵ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD>һֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼд<EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴ӹܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD>һֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
管道提供了简单的流控制机制,进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样地,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。
|
||||
|
||||
Linux <EFBFBD>йܵ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֡<EFBFBD>
|
||||
Linux 中管道是通过空文件来实现。
|
||||
|
||||
<EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>
|
||||
管道有三种:
|
||||
|
||||
1. <EFBFBD><EFBFBD>ͨ<EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>һ<EFBFBD><EFBFBD>ֻ֧<EFBFBD>ְ<EFBFBD>˫<EFBFBD><EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣻<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>֧<EFBFBD><EFBFBD>˫<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>䣻
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
|
||||
1. 普通管道:有两个限制:一是只支持半双工通信方式,即只能单向传输;二是只能在父子进程之间使用;
|
||||
2. 流管道:去除第一个限制,支持双向传输;
|
||||
3. 命名管道:去除第二个限制,可以在不相关进程之间进行通信。
|
||||
|
||||
### 2. <EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>
|
||||
### 2. 信号量
|
||||
|
||||
<EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶Թ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ķ<EFBFBD><EFBFBD>ʡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD>ֹij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڷ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>ʸ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><EFBFBD>Լ<EFBFBD>ͬһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD>߳<EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ֶΡ<EFBFBD>
|
||||
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其它进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
|
||||
|
||||
### 3. <EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3. 消息队列
|
||||
|
||||
<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD>п˷<EFBFBD><EFBFBD><EFBFBD><EFBFBD>źŴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD>١<EFBFBD><EFBFBD>ܵ<EFBFBD>ֻ<EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD>㡣
|
||||
消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
|
||||
|
||||
### 4. <EFBFBD>ź<EFBFBD>
|
||||
### 4. 信号
|
||||
|
||||
<EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ֱȽϸ<EFBFBD><EFBFBD>ӵ<EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD>ս<EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
|
||||
|
||||
### 5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
||||
### 5. 共享内存
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD>ʡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IPC <20><>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IPC <20><><EFBFBD><EFBFBD>Ч<EFBFBD>ʵͶ<CAB5>ר<EFBFBD><D7A8><EFBFBD><EFBFBD><EFBFBD>Ƶġ<C6B5><C4A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ż<EFBFBD><C5BB>ƣ<EFBFBD><C6A3><EFBFBD><EFBFBD>ź<EFBFBD><C5BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD>ʵ<EFBFBD>ֽ<EFBFBD><D6BD>̼<EFBFBD><CCBC><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
|
||||
共享内存就是映射一段能被其它进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其它 IPC 运行效率低而专门设计的。它往往与其它通信机制(如信号量)配合使用,来实现进程间的同步和通信。
|
||||
|
||||
### 6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 6. 套接字
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>һ<EFBFBD>ֽ<EFBFBD><EFBFBD>̼<EFBFBD>ͨ<EFBFBD>Ż<EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ż<EFBFBD><EFBFBD>Ʋ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>š<EFBFBD>
|
||||
套接字也是一种进程间通信机制,与其它通信机制不同的是,它可用于不同机器间的进程通信。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 经典同步问题
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۹<EFBFBD><EFBFBD><EFBFBD>
|
||||
生产者和消费者问题前面已经讨论过。
|
||||
|
||||
### 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>-д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1. 读者-写者问题
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>Լ<EFBFBD>д<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
允许多个进程同时对数据进行读操作,但是不允许读和写以及写和写操作同时发生。
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><EFBFBD><EFBFBD> count <20><>¼<EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> count_mutex <EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD> count <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> data_mutex <20><><EFBFBD>ڶԶ<DAB6>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>ݼ<EFBFBD><DDBC><EFBFBD><EFBFBD><EFBFBD>
|
||||
一个整型变量 count 记录在对数据进行读操作的进程数量,一个互斥量 count_mutex 用于对 count 加锁,一个互斥量 data_mutex 用于对读写的数据加锁。
|
||||
|
||||
```c
|
||||
typedef int semaphore;
|
||||
@ -448,7 +449,7 @@ void reader() {
|
||||
while(TRUE) {
|
||||
down(count_mutex);
|
||||
count++;
|
||||
if(count == 1) down(data_mutex); // <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹд<EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><EFBFBD><EFBFBD>
|
||||
if(count == 1) down(data_mutex); // 第一个读者需要对数据进行加锁,防止写进程访问
|
||||
up(count_mutex);
|
||||
read();
|
||||
down(count_mutex);
|
||||
@ -467,13 +468,13 @@ void writer() {
|
||||
}
|
||||
```
|
||||
|
||||
### 2. <EFBFBD><EFBFBD>ѧ<EFBFBD>ҽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 2. 哲学家进餐问题
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>Բ<EFBFBD>ܣ<EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD>Լ<EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD>ҳԷ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵĿ<EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
五个哲学家围着一张圆周,每个哲学家面前放着饭。哲学家的生活有两种交替活动:吃饭以及思考。当一个哲学家吃饭时,需要先一根一根拿起左右两边的筷子。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľⷨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱߵĿ<EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱߵĿ<EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
下面是一种错误的解法,考虑到如果每个哲学家同时拿起左手边的筷子,那么就无法拿起右手边的筷子,造成死锁。
|
||||
|
||||
```c
|
||||
#define N 5
|
||||
@ -494,7 +495,7 @@ void philosopher(int i) {
|
||||
}
|
||||
```
|
||||
|
||||
Ϊ<EFBFBD>˷<EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵĿ<EFBFBD><EFBFBD>ӣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>Ƕδ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
为了防止死锁的发生,可以加一点限制,只允许同时拿起左右两边的筷子,方法是引入一个互斥量,对拿起两个筷子的那段代码加锁。
|
||||
|
||||
```c
|
||||
semaphore mutex = 1;
|
||||
@ -515,220 +516,220 @@ void philosopher(int i) {
|
||||
}
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
# 第三章 死锁
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 死锁的条件
|
||||
|
||||

|
||||

|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EFBFBD>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ
|
||||
4. <EFBFBD><EFBFBD>·<EFBFBD>ȴ<EFBFBD>
|
||||
1. 互斥
|
||||
2. 请求与保持
|
||||
3. 不可抢占
|
||||
4. 环路等待
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѻ<EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>š<EFBFBD>
|
||||
其中,请求与保持是指一个进程因请求资源而阻塞时,对已获得的资源保持不放。
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 死锁的处理方法
|
||||
|
||||
### 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 1. 鸵鸟策略
|
||||
|
||||
<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣
|
||||
把头埋在沙子里,假装根本没发生问题。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>
|
||||
这种策略不可取。
|
||||
|
||||
### 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD>
|
||||
### 2. 死锁预防
|
||||
|
||||
<EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰԤ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在程序运行之前预防发生死锁。
|
||||
|
||||
#### 2.1 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 2.1 破坏互斥条件
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѻ<EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
例如假脱机打印机技术允许若干个进程同时输出,唯一真正请求物理打印机的进程是打印机守护进程。
|
||||
|
||||
#### 2.2 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뱣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 2.2 破坏请求与保持条件
|
||||
|
||||
һ<EFBFBD><EFBFBD>ʵ<EFBFBD>ַ<EFBFBD>ʽ<EFBFBD>ǹ涨<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD>ʼִ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>
|
||||
一种实现方式是规定所有进程在开始执行前请求所需要的全部资源。
|
||||
|
||||
#### 2.3 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#### 2.3 破坏不可抢占条件
|
||||
|
||||
#### 2.4 <EFBFBD>ƻ<EFBFBD><EFBFBD><EFBFBD>·<EFBFBD>ȴ<EFBFBD>
|
||||
#### 2.4 破坏环路等待
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դͳһ<EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ܰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>
|
||||
给资源统一编号,进程只能按编号顺序来请求资源。
|
||||
|
||||
### 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 3. 死锁避免
|
||||
|
||||
<EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ⷢ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在程序运行时避免发生死锁。
|
||||
|
||||
#### 3.1 <EFBFBD><EFBFBD>ȫ״̬
|
||||
#### 3.1 安全状态
|
||||
|
||||

|
||||

|
||||
|
||||
ͼ a <EFBFBD>ĵڶ<EFBFBD><EFBFBD><EFBFBD> has <20><>ʾ<EFBFBD><CABE>ӵ<EFBFBD>е<EFBFBD><D0B5><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> max <20><>ʾ<EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>free <20><>ʾ<EFBFBD><CABE><EFBFBD>п<EFBFBD><D0BF><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ a <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> B ӵ<><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> B<><42><EFBFBD><EFBFBD>ʱ free <20><>Ϊ 4<><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD> C <20><> A<><41>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><D0BD>̶<EFBFBD><CCB6>ܳɹ<DCB3><C9B9><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD>˿<EFBFBD><CBBF>Գ<EFBFBD>ͼ a <20><>ʾ<EFBFBD><CABE>״̬ʱ<CCAC><CAB1>ȫ<EFBFBD>ġ<EFBFBD>
|
||||
图 a 的第二列 has 表示已拥有的资源数,第三列 max 表示总共需要的资源数,free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源,运行结束后释放 B,此时 free 变为 4;接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>壺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҽ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>ͻȻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD>ֵ<EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>ʹ<EFBFBD><EFBFBD>ÿһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƹ<EFBFBD>״̬<EFBFBD>ǰ<EFBFBD>ȫ<EFBFBD>ġ<EFBFBD>
|
||||
定义:如果没有死锁发生,并且即使所有进程突然请求对资源的最大需求,也仍然存在某种调度次序能够使得每一个进程运行完毕,则称该状态是安全的。
|
||||
|
||||
#### 3.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>㷨
|
||||
#### 3.2 单个资源的银行家算法
|
||||
|
||||
һ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>мң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һȺ<EFBFBD>ͻ<EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD>㷨Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>벻<EFBFBD><EFBFBD>ȫ״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD>;ܾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD>䡣
|
||||
一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD>ͼ c Ϊ<><CEAA><EFBFBD><EFBFBD>ȫ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><E3B7A8><EFBFBD>ܾ<EFBFBD>֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD><EFBFBD>Ӷ<F3A3ACB4><D3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ c <20>е<EFBFBD>״̬<D7B4><CCAC>
|
||||
上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。
|
||||
|
||||
#### 3.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>㷨
|
||||
#### 3.3 多个资源的银行家算法
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>ͼ<EFBFBD><EFBFBD>ʾ<EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>ұߵ<EFBFBD>ͼ<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵ<EFBFBD> E<><45>P <20>Լ<EFBFBD> A <20>ֱ<EFBFBD><D6B1><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>ѷ<EFBFBD><D1B7><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> A=(1020)<29><><EFBFBD><EFBFBD>ʾ 4 <20><><EFBFBD><EFBFBD>Դ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>ʣ<EFBFBD><CAA3> 1/0/2/0<EFBFBD><EFBFBD>
|
||||
上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>״̬<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
检查一个状态是否安全的算法如下:
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұߵľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>С<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> A<><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD>ôϵͳ<CFB5><CDB3><EFBFBD>ᷢ<EFBFBD><E1B7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4>Dz<EFBFBD><C7B2><EFBFBD>ȫ<EFBFBD>ġ<EFBFBD>
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ý<EFBFBD><EFBFBD>̱<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ӵ<EFBFBD> A <20>С<EFBFBD>
|
||||
- <EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ʱ<EFBFBD><EFBFBD>ȫ<EFBFBD>ġ<EFBFBD>
|
||||
- 查找右边的矩阵是否存在一行小于等于向量 A。如果不存在这样的行,那么系统将会发生死锁,状态是不安全的。
|
||||
- 假若找到这样一行,将该进程标记为终止,并将其已分配资源加到 A 中。
|
||||
- 重复以上两步,直到所有进程都标记为终止,则状态时安全的。
|
||||
|
||||
### 4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>
|
||||
### 4. 死锁检测与死锁恢复
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ʩ<EFBFBD><EFBFBD><EFBFBD>лָ<EFBFBD><EFBFBD><EFBFBD>
|
||||
不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。
|
||||
|
||||
#### 4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
#### 4.1 死锁检测算法
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬<EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>С<EFBFBD>
|
||||
死锁检测的基本思想是,如果一个进程所请求的资源能够被满足,那么就让它执行,释放它拥有的所有资源,然后让其它能满足条件的进程执行。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
上图中,有三个进程四个资源,每个数据代表的含义如下:
|
||||
|
||||
- E <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- A <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դʣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- C <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿһ<EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- R <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- E 向量:资源总量
|
||||
- A 向量:资源剩余量
|
||||
- C 矩阵:每个进程所拥有的资源数量,每一行都代表一个进程拥有资源的数量
|
||||
- R 矩阵:每个进程请求的资源数量
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> P<sub>1</sub> <EFBFBD><EFBFBD> P<sub>2</sub> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㣬ֻ<EFBFBD>н<EFBFBD><EFBFBD><EFBFBD> P<sub>3</sub> <EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD> P<sub>3</sub> ִ<EFBFBD>У<EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> P<sub>3</sub> ӵ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ A = (2 2 2 0)<EFBFBD><EFBFBD>P<sub>1</sub> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD>ִ<EFBFBD>к<EFBFBD><EFBFBD>ͷ<EFBFBD> P<sub>1</sub> ӵ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>A = (4 2 2 2) <EFBFBD><EFBFBD>P<sub>2</sub> Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>ִ<EFBFBD>У<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
进程 P<sub>1</sub> 和 P<sub>2</sub> 所请求的资源都得不到满足,只有进程 P<sub>3</sub> 可以,让 P<sub>3</sub> 执行,之后释放 P<sub>3</sub> 拥有的资源,此时 A = (2 2 2 0)。P<sub>1</sub> 可以执行,执行后释放 P<sub>1</sub> 拥有的资源,A = (4 2 2 2) ,P<sub>2</sub> 也可以执行。所有进程都可以顺利执行,没有死锁。
|
||||
|
||||
<EFBFBD>㷨<EFBFBD>ܽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
|
||||
算法总结如下:
|
||||
|
||||
ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>ִ<EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ܱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>û<EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵĽ<EFBFBD><EFBFBD>̶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>
|
||||
每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。
|
||||
|
||||
1. Ѱ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>û<EFBFBD>б<EFBFBD><EFBFBD>ǵĽ<EFBFBD><EFBFBD><EFBFBD> P<sub>i</sub><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԴС<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD> A<><41>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD> C <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD> i <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD> A <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD>Ǹý<C7B8><C3BD>̣<EFBFBD><CCA3><EFBFBD>ת<EFBFBD><D7AA> 1<><31>
|
||||
3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD>
|
||||
1. 寻找一个没有标记的进程 P<sub>i</sub>,它所请求的资源小于等于 A。
|
||||
2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。
|
||||
3. 如果有没有这样一个进程,算法终止。
|
||||
|
||||
#### 4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>
|
||||
#### 4.2 死锁恢复
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ָ<EFBFBD>
|
||||
- ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 利用抢占恢复
|
||||
- 杀死进程
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>洢<EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 第四章 存储器管理
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
||||
## 虚拟内存
|
||||
|
||||
ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ռ䱻<EFBFBD>ָ<EFBFBD><EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬ÿһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊһҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щҳ<EFBFBD><EFBFBD>ӳ<EFBFBD>䵽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫӳ<EFBFBD>䵽<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>С<EFBFBD>
|
||||
每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>еĵ<EFBFBD>ַ<EFBFBD>ռ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD>ִ<EFBFBD>б<EFBFBD>Ҫ<EFBFBD><EFBFBD>ӳ<EFBFBD>䣬<EFBFBD><EFBFBD>ȱʧ<EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ沢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>ʧ<EFBFBD>ܵ<EFBFBD>ָ<EFBFBD>
|
||||
当程序引用到一部分在物理内存中的地址空间时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
|
||||
|
||||
## <EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
## 分页与分段
|
||||
|
||||
### 1. <EFBFBD><EFBFBD>ҳ
|
||||
### 1. 分页
|
||||
|
||||
<EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䱻<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ɹ̶<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>أ<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ռ<EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬ҳ<EFBFBD>Ϳ<EFBFBD><EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ɽ<EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɢ<EFBFBD><EFBFBD><EFBFBD>䣬<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
|
||||
用户程序的地址空间被划分为若干固定大小的区域,称为“页”。相应地,内存空间分成若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一块中,实现了离散分配,由一个页表来维护它们之间的映射关系。
|
||||
|
||||
### 2. <EFBFBD>ֶ<EFBFBD>
|
||||
### 2. 分段
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD>ͼΪһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4 <20><><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>÷<EFBFBD>ҳϵͳ<CFB5><CDB3>һά<D2BB><CEAC>ַ<EFBFBD>ռ䣬<D5BC><E4A3AC>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5>ᵼ<EFBFBD>¸<EFBFBD><C2B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3>֡<EFBFBD>
|
||||
上图为一个编译器在编译过程中建立的多个表,有 4 个表是动态增长的,如果使用分页系统的一维地址空间,动态递增的特点会导致覆盖问题的出现。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD>ֶε<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳɶΣ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ι<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䡣ÿ<EFBFBD><EFBFBD><EFBFBD>εij<EFBFBD><EFBFBD>ȿ<EFBFBD><EFBFBD>Բ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҿ<EFBFBD><EFBFBD>Զ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
分段的做法是把每个表分成段,一个段构成一个独立的地址空间。每个段的长度可以不同,并且可以动态增长。
|
||||
|
||||
ÿ<EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>
|
||||
每个段都需要程序员来划分。
|
||||
|
||||
### 3. <EFBFBD><EFBFBD>ҳʽ
|
||||
### 3. 段页式
|
||||
|
||||
<EFBFBD>÷ֶη<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>洢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䰴<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>ֳɻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĶΣ<EFBFBD><EFBFBD><EFBFBD>ÿһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD>ÿ<EFBFBD>ηֳɹ̶<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>
|
||||
用分段方法来分配和管理虚拟存储器。程序的地址空间按逻辑单位分成基本独立的段,而每一段有自己的段名,再把每段分成固定大小的若干页。
|
||||
|
||||
<EFBFBD>÷<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>档<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ȵĴ洢<EFBFBD>飬<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD>һҳ<EFBFBD><EFBFBD>
|
||||
用分页方法来分配和管理实存。即把整个主存分成与上述页大小相等的存储块,可装入作业的任何一页。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>еģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿɰ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
程序对内存的调入或调出是按页进行的,但它又可按段实现共享和保护。
|
||||
|
||||
### 4. <EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
### 4. 分页与分段区别
|
||||
|
||||
- <EFBFBD>Գ<EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿֶ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD>Ρ<EFBFBD>
|
||||
- 对程序员的透明性:分页透明,但是分段需要程序员显示划分每个段。
|
||||
|
||||
- <EFBFBD><EFBFBD>ַ<EFBFBD>ռ<EFBFBD><EFBFBD><EFBFBD>ά<EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>һά<EFBFBD><EFBFBD>ַ<EFBFBD>ռ䣬<EFBFBD>ֶ<EFBFBD><EFBFBD>Ƕ<EFBFBD>ά<EFBFBD>ġ<EFBFBD>
|
||||
- 地址空间的维度:分页是一维地址空间,分段是二维的。
|
||||
|
||||
- <EFBFBD><EFBFBD>С<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ըı䣺ҳ<EFBFBD>Ĵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ɱ䣬<EFBFBD>εĴ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̬<EFBFBD>ı䡣
|
||||
- 大小是否可以改变:页的大小不可变,段的大小可以动态改变。
|
||||
|
||||
- <EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ԭ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䣻<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>ַ<EFBFBD>ռ䲢<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
- 出现的原因:分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。
|
||||
|
||||
## ҳ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>㷨
|
||||
## 页面置换算法
|
||||
|
||||
<EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ҳ<EFBFBD>治<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пռ<EFBFBD>ʱ<EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ҳ<EFBFBD>浽<EFBFBD><EFBFBD><EFBFBD>̶Ի<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>С<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҪĿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹҳ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵ȱҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD>
|
||||
在程序运行过程中,若其所要访问的页面不在内存而需要把它们调入内存,但是内存已无空闲空间时,系统必须从内存中调出一个页面到磁盘对换区中,并且将程序所需要的页面调入内存中。页面置换算法的主要目标是使页面置换频率最低(也可以说缺页率最低)。
|
||||
|
||||
### 1. <EFBFBD><EFBFBD><EFBFBD>ѣ<EFBFBD>Optimal<EFBFBD><EFBFBD>
|
||||
### 1. 最佳(Optimal)
|
||||
|
||||
<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD>潫<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>ٱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>ȱҳ<EFBFBD>ʡ<EFBFBD>
|
||||
所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ᱻ<EFBFBD>ٷ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>
|
||||
是一种理论上的算法,因为无法知道一个页面多长时间会被再访问到。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ϵͳΪij<EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>
|
||||
举例:一个系统为某进程分配了三个物理块,并有如下页面引用序列:
|
||||
|
||||
7<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>7<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1
|
||||
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD> 7,0,1 <20><><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>װ<EFBFBD><D7B0><EFBFBD>ڴ档<DAB4><E6A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3> 2 ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȱҳ<C8B1>жϣ<D0B6><CFA3>Ὣҳ<E1BDAB><D2B3> 7 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊҳ<CEAA><D2B3> 7 <20>ٴα<D9B4><CEB1><EFBFBD><EFBFBD>ʵ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EEB3A4>
|
||||
进程运行时,先将 7,0,1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。
|
||||
|
||||
### 2. <EFBFBD>Ƚ<EFBFBD><EFBFBD>ȳ<EFBFBD><EFBFBD><EFBFBD>FIFO<EFBFBD><EFBFBD>
|
||||
### 2. 先进先出(FIFO)
|
||||
|
||||
<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD>档
|
||||
所选择换出的页面是最先进入的页面。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>Ὣ<EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ҳ<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>ʹȱҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>
|
||||
该算法会将那些经常被访问的页面也被换出,从而使缺页率升高。
|
||||
|
||||
### 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δʹ<EFBFBD>ã<EFBFBD>LRU, Least Recently Used<EFBFBD><EFBFBD>
|
||||
### 3. 最近最久未使用(LRU, Least Recently Used)
|
||||
|
||||
<EFBFBD><EFBFBD>Ȼ<EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʹ<EFBFBD>õ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥʹ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LRU <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δʹ<CEB4>õ<EFBFBD>ҳ<EFBFBD>滻<EFBFBD><E6BBBB><EFBFBD><EFBFBD>
|
||||
虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>ʵ<EFBFBD>ָ<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>ջ<EFBFBD>д洢ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>š<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD>ջ<EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δʹ<EFBFBD>õ<EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD>ס<EFBFBD>
|
||||
可以用栈来实现该算法,栈中存储页面的页面号。当进程访问一个页面时,将该页面的页面号从栈移除,并将它压入栈顶。这样,最近被访问的页面的页面号总是在栈顶,而最近最久未使用的页面的页面号总是在栈底。
|
||||
|
||||
4<EFBFBD><EFBFBD>7<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>7<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>6
|
||||
4,7,0,7,1,0,1,2,1,2,6
|
||||
|
||||

|
||||

|
||||
|
||||
### 4. ʱ<EFBFBD>ӣ<EFBFBD>Clock<EFBFBD><EFBFBD>
|
||||
### 4. 时钟(Clock)
|
||||
|
||||
Clock ҳ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>Ҫ<EFBFBD>õ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ҳ<EFBFBD>汻<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>Ϊ 1<><31>
|
||||
Clock 页面置换算法需要用到一个访问位,当一个页面被访问时,将访问为置为 1。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>һ<EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD>ȱҳ<EFBFBD>жϷ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鵱ǰָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λΪ 0<><30><EFBFBD>ͽ<EFBFBD><CDBD><EFBFBD>ҳ<EFBFBD>滻<EFBFBD><E6BBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>Ϊ 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD>ڶ<EFBFBD><DAB6>εĻ<CEB5><C4BB>ᣬ<EFBFBD>ƶ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>顣
|
||||
首先,将内存中的所有页面链接成一个循环队列,当缺页中断发生时,检查当前指针所指向页面的访问位,如果访问位为 0,就将该页面换出;否则将该页的访问位设置为 0,给该页面第二次的机会,移动指针继续检查。
|
||||
|
||||
# <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD>
|
||||
# 第五章 设备管理
|
||||
|
||||
## <EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨
|
||||
## 磁盘调度算法
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶԴ<EFBFBD><EFBFBD>̵ķ<EFBFBD><EFBFBD>ʡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD>ҪĿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD>ƽ<EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>١<EFBFBD>
|
||||
当多个进程同时请求访问磁盘时,需要进行磁盘调度来控制对磁盘的访问。磁盘调度的主要目标是使磁盘的平均寻道时间最少。
|
||||
|
||||
### 1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FCFS, First Come First Serverd<EFBFBD><EFBFBD>
|
||||
### 1. 先来先服务(FCFS, First Come First Serverd)
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʴ<EFBFBD><EFBFBD>̵<EFBFBD><EFBFBD>Ⱥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>ǹ<EFBFBD>ƽ<EFBFBD>ͼ<EFBFBD>ȱ<EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD>Ϊδ<EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><EFBFBD>Ż<EFBFBD><EFBFBD><EFBFBD>ʹƽ<EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܽϳ<EFBFBD><EFBFBD><EFBFBD>
|
||||
根据进程请求访问磁盘的先后次序来进行调度。优点是公平和简单,缺点也很明显,因为未对寻道做任何优化,使平均寻道时间可能较长。
|
||||
|
||||
### 2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD>SSTF, Shortest Seek Time First<EFBFBD><EFBFBD>
|
||||
### 2. 最短寻道时间优先(SSTF, Shortest Seek Time First)
|
||||
|
||||
Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵĴŵ<EFBFBD><EFBFBD>뵱ǰ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>ڴŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD>֤ƽ<EFBFBD><EFBFBD>Ѱ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD> FCFS <EFBFBD>úܶࡣ
|
||||
要求访问的磁道与当前磁头所在磁道距离最近的优先进行调度。这种算法并不能保证平均寻道时间最短,但是比 FCFS 好很多。
|
||||
|
||||
### 3. ɨ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>SCAN<EFBFBD><EFBFBD>
|
||||
### 3. 扫描算法(SCAN)
|
||||
|
||||
SSTF <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD>м<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵĴŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>ڴŵ<EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ڵȴ<EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ȴ<EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD>̻<EFBFBD>һֱ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD>
|
||||
SSTF 会出现进行饥饿现象。考虑以下情况,新进程请求访问的磁道与磁头所在磁道的距离总是比一个在等待的进程来的近,那么等待的进程会一直等待下去。
|
||||
|
||||
SCAN <EFBFBD>㷨<EFBFBD><EFBFBD> SSTF <EFBFBD>㷨֮<EFBFBD>Ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵĴŵ<EFBFBD><EFBFBD>ڴ<EFBFBD>ͷ<EFBFBD><EFBFBD>ǰ<EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ôһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵĴŵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>
|
||||
SCAN 算法在 SSTF 算法之上考虑了磁头的移动方向,要求所请求访问的磁道在磁头当前移动方向上才能够得到调度。因为考虑了移动方向,那么一个进程请求访问的磁道一定会得到调度。
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֳ<EFBFBD><EFBFBD><EFBFBD> SCAN <20>㷨Ϊ<E3B7A8><CEAA><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD>㷨<EFBFBD><E3B7A8>
|
||||
当一个磁头自里向外移动时,移到最外侧会改变移动方向为自外向里,这种移动的规律类似于电梯的运行,因此又常称 SCAN 算法为电梯调度算法。
|
||||
|
||||
### 4. ѭ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD><EFBFBD>CSCAN<EFBFBD><EFBFBD>
|
||||
### 4. 循环扫描算法(CSCAN)
|
||||
|
||||
CSCAN <EFBFBD><EFBFBD> SCAN <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸Ķ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD><EFBFBD>
|
||||
CSCAN 对 SCAN 进行了改动,要求磁头始终沿着一个方向移动。
|
||||
|
||||
# <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 参考资料
|
||||
|
||||
- Tanenbaum A S, Bos H. Modern operating systems[M]. Prentice Hall Press, 2014.
|
||||
- <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>ܷ<EFBFBD><DCB7><EFBFBD>, <20><>С<EFBFBD><D0A1>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ[M]. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿƼ<D3BF><C6BC><EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 2001.
|
||||
- Bryant, R. E., & O<EFBFBD><EFBFBD>Hallaron, D. R. (2004). <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ.
|
||||
- [<EFBFBD><EFBFBD><EFBFBD>̼<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>ŷ<EFBFBD>ʽ](http://blog.csdn.net/yufaw/article/details/7409596)
|
||||
- 汤子瀛, 哲凤屏, 汤小丹. 计算机操作系统[M]. 西安电子科技大学出版社, 2001.
|
||||
- Bryant, R. E., & O’Hallaron, D. R. (2004). 深入理解计算机系统.
|
||||
- [进程间的几种通信方式](http://blog.csdn.net/yufaw/article/details/7409596)
|
||||
|
941
notes/计算机网络.md
941
notes/计算机网络.md
File diff suppressed because it is too large
Load Diff
501
notes/设计模式.md
501
notes/设计模式.md
@ -1,72 +1,73 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [<EFBFBD><EFBFBD> 1 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>](#<EFBFBD><EFBFBD>-1-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>)
|
||||
* [<EFBFBD><EFBFBD> 2 <EFBFBD><EFBFBD> <20>۲<EFBFBD><DBB2><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-2-<EFBFBD><EFBFBD>-<2D>۲<EFBFBD><DBB2><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 3 <EFBFBD><EFBFBD> װ<><D7B0>ģʽ](#<EFBFBD><EFBFBD>-3-<EFBFBD><EFBFBD>-װ<><D7B0>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 4 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-4-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ)
|
||||
* [4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#41-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#42-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [4.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#43-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 5 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-5-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 6 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-6-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 7 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-7-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [7.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#71-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [7.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#72-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD> ģ<>巽<EFBFBD><E5B7BD>ģʽ](#<EFBFBD><EFBFBD>-8-<EFBFBD><EFBFBD>-ģ<>巽<EFBFBD><E5B7BD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 9 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-9-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [9.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#91-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [9.2 Java <EFBFBD><EFBFBD><EFBFBD>õĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#92-java-<EFBFBD><EFBFBD><EFBFBD>õĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [9.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ](#93-<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 10 <EFBFBD><EFBFBD> ״̬ģʽ](#<EFBFBD><EFBFBD>-10-<EFBFBD><EFBFBD>-״̬ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 11 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-11-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ)
|
||||
* [<EFBFBD><EFBFBD> 12 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-12-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD>ģʽ)
|
||||
* [第 1 章 设计模式入门](#第-1-章-设计模式入门)
|
||||
* [第 2 章 观察者模式](#第-2-章-观察者模式)
|
||||
* [第 3 章 装饰模式](#第-3-章-装饰模式)
|
||||
* [第 4 章 工厂模式](#第-4-章-工厂模式)
|
||||
* [4.1 简单工厂](#41-简单工厂)
|
||||
* [4.2 工厂方法模式](#42-工厂方法模式)
|
||||
* [4.3 抽象工厂模式](#43-抽象工厂模式)
|
||||
* [第 5 章 单件模式](#第-5-章-单件模式)
|
||||
* [第 6 章 命令模式](#第-6-章-命令模式)
|
||||
* [第 7 章 适配器模式与外观模式](#第-7-章-适配器模式与外观模式)
|
||||
* [7.1 适配器模式](#71-适配器模式)
|
||||
* [7.2 外观模式](#72-外观模式)
|
||||
* [第 8 章 模板方法模式](#第-8-章-模板方法模式)
|
||||
* [第 9 章 迭代器和组合模式](#第-9-章-迭代器和组合模式)
|
||||
* [9.1 迭代器模式](#91-迭代器模式)
|
||||
* [9.2 Java 内置的迭代器](#92-java-内置的迭代器)
|
||||
* [9.3 组合模式](#93-组合模式)
|
||||
* [第 10 章 状态模式](#第-10-章-状态模式)
|
||||
* [第 11 章 代理模式](#第-11-章-代理模式)
|
||||
* [第 12 章 复合模式](#第-12-章-复合模式)
|
||||
* [12.1 MVC](#121-mvc)
|
||||
* [<EFBFBD><EFBFBD> 13 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>ദ](#<EFBFBD><EFBFBD>-13-<EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>ദ)
|
||||
* [<EFBFBD><EFBFBD> 14 <EFBFBD><EFBFBD> ʣ<>µ<EFBFBD>ģʽ](#<EFBFBD><EFBFBD>-14-<EFBFBD><EFBFBD>-ʣ<>µ<EFBFBD>ģʽ)
|
||||
* [第 13 章 与设计模式相处](#第-13-章-与设计模式相处)
|
||||
* [第 14 章 剩下的模式](#第-14-章-剩下的模式)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
# <20><> 1 <20><> <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>
|
||||
|
||||
**1. <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD>**
|
||||
# 第 1 章 设计模式入门
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD>룬<EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧϰ<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鸴<EFBFBD>á<EFBFBD>
|
||||
**1. 设计模式概念**
|
||||
|
||||
ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD>ʻ㣬<EFBFBD>ڹ<EFBFBD>ͨʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><EFBFBD>ٵĴʻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>˽<EFBFBD><EFBFBD>ײ<EFBFBD>ϸ<EFBFBD>ڡ<EFBFBD>
|
||||
设计模式不是代码,而是解决问题的方案,学习现有的设计模式可以做到经验复用。
|
||||
|
||||
**2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
拥有设计模式词汇,在沟通时就能用更少的词汇来讨论,并且不需要了解底层细节。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѽ<EFBFBD><EFBFBD>ӵ<EFBFBD>в<EFBFBD>ͬ<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>з<EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
**2. 问题描述**
|
||||
|
||||
**3. <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>**
|
||||
设计不同种类的鸭子拥有不同的叫声和飞行方式。
|
||||
|
||||
ʹ<EFBFBD>ü̳еĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD>з<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>롣
|
||||
**3. 简单实现方案**
|
||||
|
||||

|
||||
使用继承的解决方案如下,这种方案代码无法复用,如果两个鸭子类拥有同样的飞行方式,就有两份重复的代码。
|
||||
|
||||
**4. <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>**
|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD>װ<EFBFBD>仯**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仯<EFBFBD><E4BBAF><EFBFBD><EFBFBD>Ѽ<EFBFBD>ӽкͷ<D0BA><CDB7>е<EFBFBD><D0B5><EFBFBD>Ϊ<EFBFBD><CEAA>ʽ<EFBFBD><CABD>
|
||||
**4. 设计原则**
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD>Խӿڱ<EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD><EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD><EFBFBD>ࡣ<EFBFBD><E0A1A3><EFBFBD><EFBFBD><EFBFBD>еķ<D0B5><C4B7><EFBFBD>ʵ<EFBFBD>ֲ<EFBFBD><D6B2>ڸ<EFBFBD><DAB8>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ<EFBFBD><E0A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Զ<EFBFBD>̬<EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
**封装变化**在这里变化的是鸭子叫和飞行的行为方式。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һԭ<EFBFBD><EFBFBD><EFBFBD>кͷ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֶ<EFBFBD><EFBFBD>ֲ<EFBFBD>ͬ<EFBFBD>Ľкͷ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥʵ<EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľкͷ<EFBFBD><EFBFBD>з<EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||
**针对接口编程,而不是针对实现编程** 变量声明的类型为父类,而不是具体的某个子类。父类中的方法实现不在父类,而是在各个子类。程序在运行时可以动态改变变量所指向的子类类型。
|
||||
|
||||

|
||||
运用这一原则,将叫和飞行的行为抽象出来,实现多种不同的叫和飞行的子类,让子类去实现具体的叫和飞行方式。
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü̳<EFBFBD>** <20><><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD> has-a <20><>ϵ<EFBFBD><CFB5>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>̬<EFBFBD>ı<EFBFBD>ʵ<EFBFBD>֣<EFBFBD>ֻҪͨ<D2AA><CDA8><EFBFBD>ı丸<C4B1><E4B8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>༴<EFBFBD>ɡ<EFBFBD><C9A1><EFBFBD><EFBFBD>̳оͲ<D0BE><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD>̳<EFBFBD><CCB3><EFBFBD>ϵ<EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ѿ<EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>
|
||||

|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Duck <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FlyBehavior <20><> QuackBehavior <20>࣬performQuack() <20><> performFly() <20><><EFBFBD><EFBFBD>ί<EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ʽ<EFBFBD><CABD>һ<EFBFBD><D2BB> Duck <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ը<EFBFBD><D4B8><EFBFBD><EFBFBD><EFBFBD>Ҫȥʵ<C8A5><CAB5><EFBFBD><EFBFBD> FlyBehavior <20><> QuackBehavior <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3A3ACB2><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>Զ<EFBFBD>̬<EFBFBD>ؽ<EFBFBD><D8BD>иı䡣
|
||||
**多用组合,少用继承** 组合也就是 has-a 关系,通过组合,可以在运行时动态改变实现,只要通过改变父类对象具体指向哪个子类即可。而继承就不能做到这些,继承体系在创建类时就已经确定。
|
||||
|
||||

|
||||
运用这一原则,在 Duck 类中组合 FlyBehavior 和 QuackBehavior 类,performQuack() 和 performFly() 方法委托给这两个类去处理。通过这种方式,一个 Duck 子类可以根据需要去实例化 FlyBehavior 和 QuackBehavior 的子类对象,并且也可以动态地进行改变。
|
||||
|
||||
**5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||

|
||||
|
||||

|
||||
**5. 整体设计图**
|
||||
|
||||
**6. ģʽ<C4A3><CABD><EFBFBD><EFBFBD>**
|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>壬<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD>滻<EFBFBD><E6BBBB><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD>㷨<EFBFBD>ı仯<C4B1><E4BBAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>㷨<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>
|
||||
**6. 模式定义**
|
||||
|
||||
**7. ʵ<>ִ<EFBFBD><D6B4><EFBFBD>**
|
||||
**策略模式** :定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
|
||||
|
||||
**7. 实现代码**
|
||||
|
||||
```java
|
||||
public abstract class Duck {
|
||||
@ -162,42 +163,42 @@ public class MiniDuckSimulator {
|
||||
}
|
||||
}
|
||||
```
|
||||
ִ<EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
执行结果
|
||||
```html
|
||||
QuackBehavior.Quack
|
||||
FlyBehavior.FlyWithWings
|
||||
FlyBehavior.FlyNoWay
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 2 <EFBFBD><EFBFBD> <20>۲<EFBFBD><DBB2><EFBFBD>ģʽ
|
||||
# 第 2 章 观察者模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>״̬ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣨Subject<EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><EFBFBD>۲<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD>Observer<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>۲<EFBFBD><EFBFBD>ߡ<EFBFBD>
|
||||
定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。主题(Subject)是被观察的对象,而其所有依赖者(Observer)成为观察者。
|
||||
|
||||

|
||||

|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD><EFBFBD>۲<EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD>֪ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>ߵĹ<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>ά<EFBFBD><EFBFBD>һ<EFBFBD>Ź۲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
主题中具有注册和移除观察者,并通知所有注册者的功能,主题是通过维护一张观察者列表来实现这些操作的。
|
||||
|
||||
<EFBFBD>۲<EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD>Ϊע<EFBFBD>ᡢ<EFBFBD>Ƴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>ܡ<EFBFBD>
|
||||
观察者拥有一个主题对象的引用,因为注册、移除还有数据都在主题当中,必须通过操作主题才能完成相应功能。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**3. 问题描述**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
|
||||
天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。
|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**5. 设计原则**
|
||||
|
||||
**Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>Ŭ<EFBFBD><EFBFBD>** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD>̫<EFBFBD><CCAB><EFBFBD><EFBFBD><EFBFBD>˴˵<CBB4>ϸ<EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>以<EFBFBD><E4BBA5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶Ⱥܵͣ<DCB5><CDA3><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD>е<EFBFBD><D0B5>ԣ<EFBFBD><D4A3>ܹ<EFBFBD>Ӧ<EFBFBD>Ա仯<D4B1><E4BBAF>
|
||||
**为交互对象之间的松耦合设计而努力** 当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。由于松耦合的两个对象之间互相依赖程度很低,因此系统具有弹性,能够应对变化。
|
||||
|
||||
**6. ʵ<EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD>**
|
||||
**6. 实现代码**
|
||||
|
||||
```java
|
||||
public interface Subject {
|
||||
@ -295,7 +296,7 @@ public class WeatherStation {
|
||||
}
|
||||
}
|
||||
```
|
||||
ִ<EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
执行结果
|
||||
```html
|
||||
CurrentConditionsDisplay.update:0.0 0.0 0.0
|
||||
StatisticsDisplay.update:0.0 0.0 0.0
|
||||
@ -303,39 +304,39 @@ CurrentConditionsDisplay.update:1.0 1.0 1.0
|
||||
StatisticsDisplay.update:1.0 1.0 1.0
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 3 <EFBFBD><EFBFBD> װ<><D7B0>ģʽ
|
||||
# 第 3 章 装饰模式
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 问题描述**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>Ʋ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><EFBFBD>Զ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µIJ<EFBFBD><EFBFBD>ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>̡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵļ۸<EFBFBD><EFBFBD><EFBFBD>
|
||||
设计不同种类的饮料,并且每种饮料可以动态添加新的材料,比如可以添加牛奶。计算一种饮料的价格。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD>̬<EFBFBD>ؽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>θ<EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD>˱ȼ̳и<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
动态地将责任附加到对象上。在扩展功能上,装饰者提供了比继承更有弹性的替代方案。
|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD> DarkRoast <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Mocha <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Mocha <20><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD> Whip <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6>̳<EFBFBD><CCB3><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD> cost() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cost() <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cost() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA> DarkRoast <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Mocha<68><61><EFBFBD><EFBFBD>ôֻ<C3B4><D6BB>Ҫ<EFBFBD><D2AA> Mocha <EFBFBD><EFBFBD><EFBFBD><EFBFBD> DarkRoast<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ Whip <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Whip <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Mocha<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> cost() <20><><EFBFBD><EFBFBD><EFBFBD>ܰ<EFBFBD><DCB0><EFBFBD><EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD>ļ۸<DBB8><F1B6BCB0><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5>
|
||||
下图中 DarkRoast 对象被 Mocha 包裹,Mocha 对象又被 Whip 包裹,并且他们都继承自相同父类,都有 cost() 方法,但是外层对象的 cost() 方法实现调用了内层对象的 cost() 方法。因此,如果要在 DarkRoast 上添加 Mocha,那么只需要用 Mocha 包裹 DarkRoast,如果还需要 Whip ,就用 Whip 包裹 Mocha,最后调用 cost() 方法能把三种对象的价格都包含进去。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**3. 模式类图**
|
||||
|
||||
װ<EFBFBD><EFBFBD><EFBFBD>ߺ;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߾<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>νװ<EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD>װ<EFBFBD>εĶ<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>⣬<EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ߵĹ<EFBFBD><EFBFBD>ܡ<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ߵķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><EFBFBD>ܣ<EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ߵķ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><EFBFBD>Ӷ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˱<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>ߵĹ<EFBFBD><EFBFBD>ܡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>β<EFBFBD><EFBFBD>ε<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ㣬<EFBFBD><EFBFBD>Ϊֻ<EFBFBD>о<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ʵ<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫί<EFBFBD>и<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
装饰者和具体组件都继承自组件类型,其中具体组件的方法实现不需要依赖于其它对象,而装饰者拥有一个组件类型对象,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰的对象之外,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件有直接实现而不需要委托给其它对象去处理。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 问题解决方案的类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**5. 设计原则**
|
||||
|
||||
**<EFBFBD><EFBFBD>Ӧ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺرա<EFBFBD>** Ҳ<><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¹<EFBFBD><C2B9><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ĵ<DEB8><C4B4>롣<EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µIJ<C2B5><C4B2>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫȥ<D2AA><EFBFBD><DEB8><EFBFBD><EFBFBD>ϵĴ<CFB5><C4B4>롣<EFBFBD>۲<EFBFBD><DBB2><EFBFBD>ģʽҲ<CABD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><F2A1A3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0B6BC>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>Ѹ<EFBFBD>ԭ<EFBFBD><D4AD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF>ܸı<DCB8><C4B1>ĵط<C4B5><D8B7><EFBFBD>
|
||||
**类应该对扩展开放,对修改关闭。** 也就是添加新功能时不需要修改代码。在本章问题中该原则体现在,在饮料中添加新的材料,而不需要去修改饮料的代码。观察则模式也符合这个原则。不可能所有类都能实现这个原则,应当把该原则应用于设计中最有可能改变的地方。
|
||||
|
||||
**6. Java I/O <EFBFBD>е<EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ**
|
||||
**6. Java I/O 中的装饰者模式**
|
||||
|
||||

|
||||

|
||||
|
||||
**7. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**7. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Beverage {
|
||||
@ -400,32 +401,32 @@ public class StartbuzzCoffee {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
输出
|
||||
|
||||
```html
|
||||
3.0
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 4 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 4 章 工厂模式
|
||||
|
||||
## 4.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 4.1 简单工厂
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 问题描述**
|
||||
|
||||
<EFBFBD>в<EFBFBD>ͬ<EFBFBD><EFBFBD> Pizza<7A><61><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Pizza <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
有不同的 Pizza,根据不同的情况用不同的子类实例化一个 Pizza 对象。
|
||||
|
||||
**2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>ߡ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>ݾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ<EFBFBD><EFBFBD>Ϊ<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>еĿͻ<EFBFBD><EFBFBD>Ҫ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڣ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>еĿͻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı䡣
|
||||
简单工厂不是设计模式,更像是一种编程习惯。在实例化一个超类的对象时,可以用它的所有子类来进行实例化,要根据具体需求来决定使用哪个子类。在这种情况下,把实例化的操作放到工厂来中,让工厂类来决定应该用哪个子类来实例化。这样做把客户对象和具体子类的实现解耦,客户对象不再需要知道有哪些子类以及实例化哪个子类。因为客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节,一旦子类发生改变,例如增加子类,那么所有的客户类都要发生改变。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**3. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**4. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Pizza {
|
||||
@ -471,35 +472,35 @@ public class PizzaStore {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
|
||||
```java
|
||||
CheesePizza
|
||||
```
|
||||
|
||||
## 4.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 4.2 工厂方法模式
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 问题描述**
|
||||
|
||||
ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pizza <20><><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>ķ<EFBFBD>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>磬һ<E7A3AC><D2BB><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>ŦԼ<C5A6><D4BC> cheese <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pizza <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֥<EFBFBD>Ӹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pizza <20>Dz<EFBFBD>ͬ<EFBFBD>ġ<EFBFBD>
|
||||
每个地区的 Pizza 店虽然种类相同,但是都有自己的风味,需要单独区分。例如,一个客户点了纽约的 cheese 种类的 Pizza 和在芝加哥点的相同种类的 Pizza 是不同的。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴٵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ
|
||||
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
|
||||
|
||||
**3. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**3. 模式类图**
|
||||
|
||||
<EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>ڹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>У<EFBFBD>Creator <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> anOperation() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>õ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。下图中,Creator 有一个 anOperation() 方法,这个方法需要用到一组产品类,这组产品类由每个子类来创建。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ഴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʒ<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD>ǰѼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD>Ʒ<EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可以为每个子类创建单独的简单工厂来创建每一个产品类,但是把简单工厂中创建对象的代码放到子类中来可以减少类的数目,因为子类不算是产品类,因此完全可以这么做。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**5. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Pizza {
|
||||
@ -588,36 +589,36 @@ public class PizzaTestDrive {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
|
||||
```html
|
||||
NYStyleCheesePizza is making..
|
||||
ChicagoStyleCheesePizza is making..
|
||||
```
|
||||
|
||||
## 4.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 4.3 抽象工厂模式
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**1. 设计原则**
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**<2A><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ<EFBFBD><E0A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խӿڱ<D3BF><DAB1>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֱ<EFBFBD><D6B1>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>˵<EFBFBD><CBB5><EFBFBD>ˣ<EFBFBD><CBA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø߲<C3B8><DFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD><D2A3><EFBFBD><EFBFBD>ܸ߲<DCB8><DFB2><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><DAB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>磬<EFBFBD><E7A3AC>ͼ<EFBFBD><CDBC> PizzaStore <20><><EFBFBD>ڸ߲<DAB8><DFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Pizza <20>ij<EFBFBD><C4B3><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF>Բ<EFBFBD><D4B2>ù<EFBFBD><C3B9><EFBFBD> Pizza <20>ľ<EFBFBD><C4BE><EFBFBD>ʵ<EFBFBD><CAB5>ϸ<EFBFBD>ڡ<EFBFBD>
|
||||
**依赖倒置原则**:要依赖抽象,不要依赖具体类。听起来像是针对接口编程,不针对实现编程,但是这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或底层组件,两者都应该依赖于抽象。例如,下图中 PizzaStore 属于高层组件,它依赖的是 Pizza 的抽象类,这样就可以不用关心 Pizza 的具体实现细节。
|
||||
|
||||

|
||||

|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 模式定义**
|
||||
|
||||
<EFBFBD>ṩһ<EFBFBD><EFBFBD><EFBFBD>ӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD>壬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ȷָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ
|
||||
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
|
||||
|
||||
**3. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**3. 模式类图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>壬Ҳ<EFBFBD><EFBFBD><EFBFBD>Ǻܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>صģ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD>кܴ<EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽҲ<EFBFBD>õ<EFBFBD><EFBFBD>˹<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>AbstractFactory <EFBFBD>е<EFBFBD> CreateProductA <EFBFBD><EFBFBD> CreateProductB <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϲ<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD>Ķ<EFBFBD><EFBFBD>塣<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Client <EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD>Client Ҫͨ<EFBFBD><EFBFBD> AbstractFactory ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>Client <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӹ߲<D3B8><DFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD><CFA3><EFBFBD> Cilent <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AbstractFactory <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽʹ<EFBFBD><EFBFBD><EFBFBD>˼̳С<EFBFBD>
|
||||
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。并且,抽象工厂模式也用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 CreateProductA 和 CreateProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要这两个对象的协作才能完成任务。从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory ,而工厂模式使用了继承。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**5. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Dough {
|
||||
@ -719,28 +720,28 @@ public class NYPizzaStoreTestDrive {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
|
||||
```html
|
||||
ThickCrustDough
|
||||
MarinaraSauce
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 5 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 5 章 单件模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
ȷ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ȫ<EFBFBD>ַ<EFBFBD><EFBFBD>ʵ㡣
|
||||
确保一个类只有一个实例,并提供了一个全局访问点。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD> Java ʵ<><CAB5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>˽<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>˽<EFBFBD>о<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ú<EFBFBD><C3BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽<EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>ú<EFBFBD><C3BA><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ψһ<CEA8><D2BB>˽<EFBFBD>о<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
单件模式的 Java 实现用一个私有构造器、一个私有静态变量以及一个公有静态函数,该函数返回私有变量,使得所有通过该函数获取的对象都指向这个唯一的私有静态变量。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**3. 经典实现**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>˽<EFBFBD>о<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳٻ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĺô<EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD>ô<EFBFBD>Ͳ<EFBFBD><EFBFBD>ᴴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˽<EFBFBD>о<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD>̻߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>ܹ<EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> if(uniqueInstance == null) <EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬<EFBFBD><EFBFBD>ô<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> uniqueInstance ˽<EFBFBD>о<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
以下实现中,私有静态变量被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会创建该私有静态变量,从而节约资源。这个实现在多线程环境下是不安全的,因为多个线程能够同时进入 if(uniqueInstance == null) 内的语句块,那么就会多次实例化 uniqueInstance 私有静态变量。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
@ -759,9 +760,9 @@ public class Singleton {
|
||||
}
|
||||
```
|
||||
|
||||
**4. <EFBFBD>̲߳<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ**
|
||||
**4. 线程不安全问题的解决方案一**
|
||||
|
||||
ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> getUniqueInstance() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ø÷<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>̷߳<EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD> uniqueInstance <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣<EFBFBD><E2A1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ֻ<EFBFBD><D6BB>һ<EFBFBD><D2BB><EFBFBD>߳̽<DFB3><CCBD>룬<EFBFBD><EBA3AC><EFBFBD><EFBFBD><EFBFBD>ϻ<EFBFBD><CFBB><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>˷ѡ<CBB7>
|
||||
只需要对 getUniqueInstance() 方法加锁,就能让该方法一次只能一个线程访问,从而避免了对 uniqueInstance 变量进行多次实例化的问题。但是这样有一个问题是一次只能一个线程进入,性能上会有一定的浪费。
|
||||
|
||||
```java
|
||||
public static synchronized Singleton getUniqueInstance() {
|
||||
@ -772,17 +773,17 @@ public class Singleton {
|
||||
}
|
||||
```
|
||||
|
||||
**5. <EFBFBD>̲߳<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**5. 线程不安全问题的解决方案二**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
不用延迟实例化,采用直接实例化。
|
||||
|
||||
```java
|
||||
private static Singleton uniqueInstance = new Singleton();
|
||||
```
|
||||
|
||||
**6. <EFBFBD>̲߳<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**6. 线程不安全问题的解决方案三**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӷ<EFBFBD> getUniqueInstance() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>ֻ<EFBFBD><D6BB>Ҫ<EFBFBD><D2AA> uniqueInstance = new Singleton(); <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> uniqueInstance <20>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
考虑第一个解决方案,它是直接对 getUniqueInstance() 方法进行加锁,而实际上只需要对 uniqueInstance = new Singleton(); 这条语句加锁即可。使用两个条件语句来判断 uniqueInstance 是否已经实例化,如果没有实例化才需要加锁。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
@ -805,31 +806,31 @@ public class Singleton {
|
||||
}
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 6 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 6 章 命令模式
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 问题描述**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>кܶఴť<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť<EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>зdz<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļҵ磬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӽҵ硣
|
||||
设计一个遥控器,它有很多按钮,每个按钮可以发起一个命令,让一个家电完成相应操作。有非常多的家电,并且也会增加家电。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>ɶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ա<EFBFBD>ʹ<EFBFBD>ò<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
将命令封装成对象,以便使用不同的命令来参数化其它对象。
|
||||
|
||||
**3. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**3. 模式类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||
Invoker <EFBFBD><EFBFBD>ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> execute() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Receiver <EFBFBD>ǵ<EFBFBD><EFBFBD>ƣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>ConcreteCommand <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Receiver <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>ί<EFBFBD>и<EFBFBD> Receiver <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD> LightOnCommand <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> excute <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD>и<EFBFBD> Light <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Light <20><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> on() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><C9B2><EFBFBD><EFBFBD><EFBFBD>Invoker <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Client <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Invoker <20><><EFBFBD><EFBFBD><EFBFBD>ɵģ<C9B5><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Client <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><D0A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Invoker 是遥控器,它可以设置命令,并且调用命令对象的 execute() 方法。Receiver 是电灯,是命令真正的执行者。ConcreteCommand 类组合了一个 Receiver 对象,命令的执行委托给 Receiver 对象来处理,也就是 LightOnCommand 命令的 excute 方法委托给 Light 对象来处理,Light 对象通过调用 on() 方法来完成操作。Invoker 不是 Client 对象,是因为命令的创建不是在 Invoker 中完成的,因此需要额外的 Client 对象来处理这些操作。
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**5. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Command {
|
||||
@ -864,7 +865,7 @@ public class LightOnCommand implements Command{
|
||||
```
|
||||
```java
|
||||
/**
|
||||
* ң<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* 遥控器类
|
||||
*/
|
||||
public class SimpleRemoteControl {
|
||||
Command slot;
|
||||
@ -895,39 +896,39 @@ public class RemoteLoader {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
输出
|
||||
|
||||
```html
|
||||
Light is on!
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 7 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 7 章 适配器模式与外观模式
|
||||
|
||||
## 7.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 7.1 适配器模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľӿڣ<EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ӿڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>䡣
|
||||
将一个类的接口,转换为客户期望的另一个接口。适配器让原本不兼容的类可以合作无间。
|
||||
|
||||

|
||||

|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣨAdapter<EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Adaptee<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD>и<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ̳У<EFBFBD>Adapter <EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD> Target <EFBFBD><EFBFBD> Adaptee <EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD>Ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Adaptee <20><><EFBFBD><EFBFBD>Ȼ<EFBFBD><C8BB>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> Adapter <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٰ<EFBFBD><D9B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Target <20><><EFBFBD>͵ģ<CDB5><C4A3><EFBFBD><EFBFBD><EFBFBD> Client <20>Ϳ<EFBFBD><CDBF><EFBFBD><D4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Target <20>Ķ<EFBFBD><C4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
有两种适配器模式的实现,一种是对象方式,一种是类方式。对象方式是通过组合的方法,让适配器类(Adapter)拥有一个待适配的对象(Adaptee),从而把相应的处理委托给待适配的对象。类方式用到多重继承,Adapter 可以看成 Target 和 Adaptee 类型,先把它当成 Adaptee 类型然后实例化一个 Adapter 对象,再把它当成 Target 类型的,这样 Client 就可以把这个对象当成 Target 的对象来处理。
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**3. 问题描述**
|
||||
|
||||
<EFBFBD><EFBFBD>Ѽ<EFBFBD>ӣ<EFBFBD>Duck<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Turkey<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Duck <EFBFBD><EFBFBD> quack() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Turkey ֻ<EFBFBD><EFBFBD> gobble() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD> Turkey Ҳ<EFBFBD><EFBFBD> Duck <EFBFBD><EFBFBD> quack() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
让鸭子(Duck)适配火鸡(Turkey),Duck 有 quack() 方法,而 Turkey 只有 gobble() 方法。也就是要让 Turkey 也有 Duck 的 quack() 方法。
|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**5. 代码实现**
|
||||
|
||||
```java
|
||||
public interface Duck {
|
||||
@ -984,69 +985,69 @@ public class DuckTestDrive {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
```html
|
||||
gobble!
|
||||
fly!
|
||||
```
|
||||
|
||||
## 7.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 7.2 外观模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD>ṩ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ͳһ<EFBFBD>Ľӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>е<EFBFBD>һȺ<EFBFBD>ӿڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><EFBFBD>ӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD>
|
||||
提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**3. 问题描述**
|
||||
|
||||
<EFBFBD><EFBFBD>ͥӰԺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>йۿ<EFBFBD><EFBFBD><EFBFBD>Ӱʱ<EFBFBD><EFBFBD>Ҫ<EFBFBD>Ժܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ü<EFBFBD>ͥӰԺ<EFBFBD><EFBFBD>ֻ<EFBFBD>ṩһ<EFBFBD><EFBFBD><EFBFBD>Ľӿڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD>Ľӿڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>þ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
家庭影院中有众多电器,当要进行观看电影时需要对很多电器进行操作。要求简化这些操作,使得家庭影院类只提供一个简化的接口,例如提供一个看电影的接口而不用具体操作众多电器。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**5. 设计原则**
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ʶԭ<EFBFBD><EFBFBD>**<2A><>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD><CCB8><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ʹ<EFBFBD>ÿͻ<C3BF><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>١<EFBFBD>
|
||||
**最少知识原则**:只和你的密友谈话。也就是应当使得客户对象所需要交互的对象应当尽可能少。
|
||||
|
||||
# <EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD> ģ<>巽<EFBFBD><E5B7BD>ģʽ
|
||||
# 第 8 章 模板方法模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>ĹǼܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӳٵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
|
||||
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。
|
||||
|
||||
ģ<EFBFBD>巽<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>㷨<EFBFBD>ṹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>е<EFBFBD>ijЩ<EFBFBD><EFBFBD><EFBFBD>衣
|
||||
模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||
ģ<EFBFBD>巽<EFBFBD><EFBFBD> templateMethod() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㷨<EFBFBD>ĹǼܣ<EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> primitiveOperation1() <EFBFBD><EFBFBD> primitiveOperation2() <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>е<EFBFBD>˳<EFBFBD><EFBFBD> primitiveOperation1() <EFBFBD><EFBFBD> primitiveOperation2() <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֡<EFBFBD>
|
||||
模板方法 templateMethod() 定义了算法的骨架,确定了 primitiveOperation1() 和 primitiveOperation2() 方法执行的顺序,而 primitiveOperation1() 和 primitiveOperation2() 让子类去具体实现。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**3. 问题描述**
|
||||
|
||||
<EFBFBD>忧<EFBFBD>Ⱥͳ<EFBFBD><EFBFBD>趼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ijЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е㲻һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ**
|
||||
**4. 解决方案类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**5. 设计原则**
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>绰<EFBFBD><E7BBB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3><EFBFBD><EFBFBD>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>绰<EFBFBD><E7BBB0><EFBFBD><EFBFBD><EFBFBD>㡣<EFBFBD><E3A1A3>һԭ<D2BB><D4AD><EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD>߲<EFBFBD><DFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ģ<EFBFBD>巽<EFBFBD><E5B7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ֻ<EFBFBD>и<EFBFBD><D0B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>࣬<EFBFBD><E0A3AC><EFBFBD><EFBFBD><E0B2BB><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8>ࡣ
|
||||
**好莱坞原则**:别调用(打电话给)我们,我们会调用(打电话给)你。这一原则可以防止依赖腐败,即防止高层组件依赖底层组件,底层组件又依赖高层组件。该原则在模板方法的体现为,只有父类会调用子类,子类不会调用父类。
|
||||
|
||||
**6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**6. 钩子**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD>hock<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ijЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬʵ<EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ޣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȶ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>ʲô<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ģ<EFBFBD>巽<EFBFBD><EFBFBD> templteMethod() <20>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><CDB8><EFBFBD>Ĭ<EFBFBD><C4AC>ʵ<EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD>ʵ<EFBFBD>֡<EFBFBD>
|
||||
钩子(hock):某些步骤在不同实现中可有可无,可以先定义一个什么都不做的方法,把它加到模板方法 templteMethod() 中,如果子类需要它就覆盖默认实现并加上自己的实现。
|
||||
|
||||
**7. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**7. 代码实现**
|
||||
|
||||
```java
|
||||
public abstract class CaffeineBeverage {
|
||||
@ -1109,7 +1110,7 @@ public class CaffeineBeverageTestDrive {
|
||||
}
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
|
||||
```html
|
||||
boilWater
|
||||
@ -1123,21 +1124,21 @@ pourInCup
|
||||
Tea.addCondiments
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 9 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 9 章 迭代器和组合模式
|
||||
|
||||
## 9.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 9.1 迭代器模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD>ṩһ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ۺ϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĸ<EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD>¶<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>ı<EFBFBD>ʾ<EFBFBD><EFBFBD>
|
||||
提供一种顺序访问一个聚合对象中的各个元素的方法,而又不暴露其内部的表示。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||
<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ۺ϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǿۺ϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵġ<EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>þۺ϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
客户类拥有一个聚合对象和迭代器对象,迭代器对象是聚合对象生成的。只需要迭代器定义好移动的操作,就可以让聚合对象能够顺序遍历。
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**3. 代码实现**
|
||||
|
||||
```java
|
||||
public class Aggregate {
|
||||
@ -1195,7 +1196,7 @@ public class Client {
|
||||
}
|
||||
}
|
||||
```
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
```html
|
||||
0
|
||||
1
|
||||
@ -1209,13 +1210,13 @@ public class Client {
|
||||
9
|
||||
```
|
||||
|
||||
## 9.2 Java <EFBFBD><EFBFBD><EFBFBD>õĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
## 9.2 Java 内置的迭代器
|
||||
|
||||
**1. ʵ<EFBFBD>ֽӿ<EFBFBD>**
|
||||
**1. 实现接口**
|
||||
|
||||
Java <EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Iterator <EFBFBD>ӿڣ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> Java ʵ<><CAB5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ҫ<EFBFBD>þۺ϶<DBBA><CFB6><EFBFBD>ʵ<EFBFBD><CAB5> Iterable <20>ӿڣ<D3BF><DAA3>ýӿ<C3BD><D3BF><EFBFBD>һ<EFBFBD><D2BB> iterator() <20><><EFBFBD><EFBFBD><EFBFBD>᷵<EFBFBD><E1B7B5>һ<EFBFBD><D2BB> Iterator <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> Java <20><><EFBFBD>õĵ<C3B5><C4B5><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> foreach ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۺ϶<DBBA><CFB6><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF>Ԫ<EFBFBD>ء<EFBFBD>
|
||||
Java 中已经有了 Iterator 接口,在使用 Java 实现时,需要让聚合对象实现 Iterable 接口,该接口有一个 iterator() 方法会返回一个 Iterator 对象。使用 Java 内置的迭代器实现,客户对象可以使用 foreach 循环来遍历聚合对象中的每个元素。
|
||||
|
||||
**2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**2. 代码实现**
|
||||
|
||||
```java
|
||||
import java.util.Iterator;
|
||||
@ -1271,25 +1272,25 @@ public class Client {
|
||||
}
|
||||
```
|
||||
|
||||
## 9.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
|
||||
## 9.3 组合模式
|
||||
|
||||
**1. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>**
|
||||
**1. 设计原则**
|
||||
|
||||
һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
一个类应该只有一个引起改变的原因。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>νṹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> / <20><><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>νṹ<CEBD><E1B9B9>
|
||||
允许将对象组合成树形结构来表现“整体 / 部分”层次结构。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿͻ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>µķ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
组合能让客户以一致的方式处理个别对象以及对象组合。
|
||||
|
||||
**3. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**3. 模式类图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>Composite<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Component<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>νṹ<EFBFBD><EFBFBD><EFBFBD>м䣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
|
||||
由于组合(Composite)类拥有一个组件(Component)对象,因此组合对象位于树形结构的中间,它还可以继续操作这个组件对象,并忽略组件对象的具体类型。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**4. 代码实现**
|
||||
|
||||
```java
|
||||
public abstract class Component {
|
||||
@ -1316,7 +1317,7 @@ public class Leaf extends Component {
|
||||
|
||||
@Override
|
||||
public void addChild(Component component) {
|
||||
throw new UnsupportedOperationException(); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><EFBFBD>һְ<EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD> , <20><><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ӽڵ㻹<DAB5><E3BBB9><EFBFBD><EFBFBD><EFBFBD>Ͻڵ<CFBD>
|
||||
throw new UnsupportedOperationException(); // 牺牲透明性换取单一职责原则 , 这样就不用考虑是叶子节点还是组合节点
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1378,7 +1379,7 @@ public class Client {
|
||||
}
|
||||
}
|
||||
```
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
|
||||
```html
|
||||
Composite:root
|
||||
@ -1390,56 +1391,56 @@ Composite:root
|
||||
--left:3
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 10 <EFBFBD><EFBFBD> ״̬ģʽ
|
||||
# 第 10 章 状态模式
|
||||
|
||||
**1. ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1. 模式定义**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>״̬<EFBFBD>ı<EFBFBD>ʱ<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ
|
||||
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
|
||||
|
||||
״̬ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD>ģʽһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ģʽ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵIJ<EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>磬״̬ģʽ<EFBFBD>£<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ί<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ܷ<EFBFBD><EFBFBD><EFBFBD>״̬ת<EFBFBD>ƣ<EFBFBD>ʹ<EFBFBD>ÿͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>е<EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı䡣״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ֵġ<EFBFBD>
|
||||
状态模式的类图和策略模式一样,并且都是能够动态改变对象的行为。但是状态模式是通过状态对象的状态转移来改变客户对象组合的状态对象,而策略模式是通过客户对象本身的决策来改变组合的策略对象。例如,状态模式下,客户对象委托状态对象进行一个处理操作,那么状态对象有可能发生状态转移,使得客户对象拥有的状态对象发生改变。状态对象组合了客户对象,状态转移是状态对象通过改变客户对象所组合的状态对象实现的。
|
||||
|
||||
**2. ģʽ<EFBFBD><EFBFBD>ͼ**
|
||||
**2. 模式类图**
|
||||
|
||||

|
||||

|
||||
|
||||
**3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**3. 问题描述**
|
||||
|
||||
<EFBFBD>ǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۻ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۻ<EFBFBD><EFBFBD>в<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD>Է<EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>ƣ<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ۻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ΪҲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı䡣
|
||||
糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。
|
||||
|
||||

|
||||

|
||||
|
||||
**4. ֱ<EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**4. 直接解决方案**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ǹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬<EFBFBD>жϵ<EFBFBD>ǰ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>ͬ<EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD>в<EFBFBD>ͬ<EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD>״̬ת<EFBFBD>ơ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ʵ<EFBFBD><EFBFBD>ϸ<EFBFBD>ڶ<EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD>࣬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫȥ<EFBFBD>Ŀͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD>롣
|
||||
在糖果机的每个操作函数里面,判断当前的状态,根据不同的状态进行不同的处理,并且发生不同的状态转移。这种解决方案把所有的实现细节都放到客户类,这样在新增状态的时候就要去修改客户类的代码。
|
||||
|
||||

|
||||

|
||||
|
||||
**5. ʹ<EFBFBD><EFBFBD>״̬ģʽ<EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**5. 使用状态模式的解决方案**
|
||||
|
||||
״̬<EFBFBD><EFBFBD>ת<EFBFBD>Ʊ<EFBFBD><EFBFBD>Ƶ<EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>棬<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫί<EFBFBD>и<EFBFBD>״̬<EFBFBD>༴<EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>ʲô״̬<EFBFBD>Լ<EFBFBD>״̬ʱ<EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD>Ƶġ<EFBFBD>
|
||||
状态的转移被移到状态类里面,客户类的每个操作只需要委托给状态类即可,而不需要知道当前是什么状态以及状态时如何进行转移的。
|
||||
|
||||
|
||||
**6. <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>**
|
||||
**6. 代码实现**
|
||||
|
||||
```java
|
||||
public interface State {
|
||||
/**
|
||||
* Ͷ<EFBFBD><EFBFBD>25 <20><>Ǯ
|
||||
* 投入25 分钱
|
||||
*/
|
||||
void insertQuarter();
|
||||
|
||||
/**
|
||||
* <EFBFBD>˻<EFBFBD>25 <20><>Ǯ
|
||||
* 退回25 分钱
|
||||
*/
|
||||
void ejectQuarter();
|
||||
|
||||
/**
|
||||
* ת<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* 转动曲柄
|
||||
*/
|
||||
void turnCrank();
|
||||
|
||||
/**
|
||||
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ<EFBFBD>
|
||||
* 发放糖果
|
||||
*/
|
||||
void dispense();
|
||||
}
|
||||
@ -1667,7 +1668,7 @@ public class GumballMachineTestDrive {
|
||||
}
|
||||
}
|
||||
```
|
||||
<EFBFBD><EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>
|
||||
运行结果
|
||||
```html
|
||||
You insert a quarter
|
||||
You turned...
|
||||
@ -1696,34 +1697,34 @@ You turned, but there are no gumballs
|
||||
No gumball dispensed
|
||||
```
|
||||
|
||||
# <EFBFBD><EFBFBD> 11 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 11 章 代理模式
|
||||
|
||||
# <EFBFBD><EFBFBD> 12 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ģʽ
|
||||
# 第 12 章 复合模式
|
||||
|
||||
## 12.1 MVC
|
||||
|
||||
**<EFBFBD><EFBFBD>ͳ MVC**
|
||||
**传统 MVC**
|
||||
|
||||
<EFBFBD><EFBFBD>ͼʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>˹۲<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>
|
||||
视图使用组合模式,模型使用了观察者模式,控制器使用了策略模式。
|
||||
|
||||

|
||||

|
||||
|
||||
**Web <EFBFBD>е<EFBFBD> MVC**
|
||||
**Web 中的 MVC**
|
||||
|
||||
ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ù۲<EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD>
|
||||
模式不再使用观察者模式。
|
||||
|
||||

|
||||

|
||||
|
||||
# <EFBFBD><EFBFBD> 13 <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3>ദ
|
||||
# 第 13 章 与设计模式相处
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>壺<EFBFBD><EFBFBD>ij **<EFBFBD>龳** <20>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD>ij **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>** <20><>ij<EFBFBD><C4B3> **<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**<2A><>
|
||||
定义:在某 **情境** 下,针对某 **问题** 的某种 **解决方案**。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD>´<EFBFBD><EFBFBD>뱻<EFBFBD><EFBFBD><EFBFBD>ȹ<EFBFBD><EFBFBD>̻<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫģʽ<EFBFBD>ĵط<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
过度使用设计模式可能导致代码被过度工程化,应该总是用最简单的解决方案完成工作,并在真正需要模式的地方才使用它。
|
||||
|
||||
<EFBFBD><EFBFBD>ģʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õĽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>˾<EFBFBD><EFBFBD>治Ҫʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
反模式:不好的解决方案来解决一个问题。主要作用是为了警告不要使用这些解决方案。
|
||||
|
||||
ģʽ<EFBFBD><EFBFBD><EFBFBD>ࣺ
|
||||
模式分类:
|
||||
|
||||

|
||||

|
||||
|
||||
# <EFBFBD><EFBFBD> 14 <EFBFBD><EFBFBD> ʣ<>µ<EFBFBD>ģʽ
|
||||
# 第 14 章 剩下的模式
|
||||
|
763
notes/重构.md
763
notes/重构.md
File diff suppressed because it is too large
Load Diff
251
notes/面向对象思想.md
251
notes/面向对象思想.md
@ -1,75 +1,76 @@
|
||||
<!-- GFM-TOC -->
|
||||
* [S.O.L.I.D](#solid)
|
||||
* [1. <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>](#1-<2D><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>)
|
||||
* [2. <EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>](#2-<2D><><EFBFBD>ŷ<EFBFBD><C5B7><EFBFBD>ԭ<EFBFBD><D4AD>)
|
||||
* [3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻ԭ<EFBFBD><EFBFBD>](#3-<2D><><EFBFBD><EFBFBD><EFBFBD>滻ԭ<E6BBBB><D4AD>)
|
||||
* [4. <EFBFBD>ӿڷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>](#4-<2D>ӿڷ<D3BF><DAB7><EFBFBD>ԭ<EFBFBD><D4AD>)
|
||||
* [5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>](#5-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>)
|
||||
* [<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>̳С<EFBFBD><EFBFBD><EFBFBD>̬](#<23><>װ<EFBFBD>̳ж<CCB3>̬)
|
||||
* [1. <EFBFBD><EFBFBD>װ](#1-<EFBFBD><EFBFBD>װ)
|
||||
* [2. <EFBFBD>̳<EFBFBD>](#2-<EFBFBD>̳<EFBFBD>)
|
||||
* [3. <EFBFBD><EFBFBD>̬](#3-<EFBFBD><EFBFBD>̬)
|
||||
* [1. 单一责任原则](#1-单一责任原则)
|
||||
* [2. 开放封闭原则](#2-开放封闭原则)
|
||||
* [3. 里氏替换原则](#3-里氏替换原则)
|
||||
* [4. 接口分离原则](#4-接口分离原则)
|
||||
* [5. 依赖倒置原则](#5-依赖倒置原则)
|
||||
* [封装、继承、多态](#封装继承多态)
|
||||
* [1. 封装](#1-封装)
|
||||
* [2. 继承](#2-继承)
|
||||
* [3. 多态](#3-多态)
|
||||
* [UML](#uml)
|
||||
* [1. <EFBFBD><EFBFBD>ͼ](#1-<EFBFBD><EFBFBD>ͼ)
|
||||
* [2. ʱ<EFBFBD><EFBFBD>ͼ](#2-ʱ<EFBFBD><EFBFBD>ͼ)
|
||||
* [<EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](#<23>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD>)
|
||||
* [1. 类图](#1-类图)
|
||||
* [2. 时序图](#2-时序图)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
# S.O.L.I.D
|
||||
|
||||
S.O.L.I.D<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƺͱ<EFBFBD><EFBFBD><EFBFBD>(OOD&OOP)<29>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>(Programming Priciple)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>
|
||||
S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写。
|
||||
|
||||
|<EFBFBD><EFBFBD>д |ȫƴ |<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>|
|
||||
|简写 |全拼 |中文翻译|
|
||||
| -- | -- | -- |
|
||||
|SRP| The Single Responsibility Principle |<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>|
|
||||
|OCP| The Open Closed Principle | <EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>|
|
||||
|LSP| The Liskov Substitution Principle |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻ԭ<EFBFBD><EFBFBD>|
|
||||
|ISP| The Interface Segregation Principle |<EFBFBD>ӿڷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>|
|
||||
|DIP| The Dependency Inversion Principle |<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>|
|
||||
|SRP| The Single Responsibility Principle |单一责任原则|
|
||||
|OCP| The Open Closed Principle | 开放封闭原则|
|
||||
|LSP| The Liskov Substitution Principle |里氏替换原则|
|
||||
|ISP| The Interface Segregation Principle |接口分离原则|
|
||||
|DIP| The Dependency Inversion Principle |依赖倒置原则|
|
||||
|
||||
|
||||
## 1. <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>
|
||||
## 1. 单一责任原则
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>仰˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࡣ
|
||||
当需要修改某个类的时候原因有且只有一个。换句话说就是让一个类只做一种类型责任,当这个类需要承当其他类型的责任的时候,就需要分解这个类。
|
||||
|
||||
## 2. <EFBFBD><EFBFBD><EFBFBD>ŷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>
|
||||
## 2. 开放封闭原则
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵġ<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD>ǿ<EFBFBD><EFBFBD>ŵģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD>յġ<EFBFBD>
|
||||
软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
|
||||
|
||||
## 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻ԭ<EFBFBD><EFBFBD>
|
||||
## 3. 里氏替换原则
|
||||
|
||||
<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD>滻<EFBFBD>κ<EFBFBD><EFBFBD>䳬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>ž<EFBFBD><EFBFBD><EFBFBD> is-a <EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
|
||||
当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有 is-a 关系。
|
||||
|
||||
## 4. <EFBFBD>ӿڷ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>
|
||||
## 4. 接口分离原则
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD>ʹ<EFBFBD>õĽӿڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>仰˵<EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD>ŵĽӿڱ<EFBFBD>ʹ<EFBFBD>õ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ܽӿ<EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>á<EFBFBD>
|
||||
不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口总要好。
|
||||
|
||||
## 5. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD>
|
||||
## 5. 依赖倒置原则
|
||||
|
||||
1. <EFBFBD>߲<EFBFBD>ģ<EFBFBD>鲻Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵͲ<EFBFBD>ģ<EFBFBD>飬<EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڣ<EFBFBD>ϸ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD>
|
||||
1. 高层模块不应该依赖于低层模块,二者都应该依赖于抽象
|
||||
2. 抽象不应该依赖于细节,细节应该依赖于抽象
|
||||
|
||||
# <EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>̳С<EFBFBD><EFBFBD><EFBFBD>̬
|
||||
# 封装、继承、多态
|
||||
|
||||
<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD>̳С<EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԡ<EFBFBD>
|
||||
封装、继承、多态是面向对象的三大特性。
|
||||
|
||||
## 1. <EFBFBD><EFBFBD>װ
|
||||
## 1. 封装
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵIJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>乹<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɷָ<EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>壬<EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڣ<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>ʹ֮<EFBFBD><EFBFBD><EFBFBD>ⲿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD>ڣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṩ<EFBFBD>Ľӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʸö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户是无需知道对象内部的细节,但可以通过该对象对外的提供的接口来访问该对象。
|
||||
|
||||
<EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD>
|
||||
封装有三大好处:
|
||||
|
||||
1. <EFBFBD><EFBFBD><EFBFBD>õķ<EFBFBD>װ<EFBFBD>ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD>
|
||||
1. 良好的封装能够减少耦合。
|
||||
|
||||
2. <EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><EFBFBD>Ľṹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD>
|
||||
2. 类内部的结构可以自由修改。
|
||||
|
||||
3. <EFBFBD><EFBFBD><EFBFBD>ԶԳ<EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ơ<EFBFBD>
|
||||
3. 可以对成员进行更精确的控制。
|
||||
|
||||
4. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ϸ<EFBFBD>ڡ<EFBFBD>
|
||||
4. 隐藏信息,实现细节。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD> Person <EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ name<EFBFBD><EFBFBD>gender<EFBFBD><EFBFBD>age <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD> get() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡһ<C8A1><D2BB> Person <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> name <EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD> gender <EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ age <20><><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD> age <20><><EFBFBD>Կ<EFBFBD><D4BF>Թ<EFBFBD> work() <20><><EFBFBD><EFBFBD>ʹ<EFBFBD>á<EFBFBD>
|
||||
以下 Person 类封装 name、gender、age 等属性,外界只能通过 get() 方法获取一个 Person 对象的 name 属性和 gender 属性,而无法获取 age 属性,但是 age 属性可以供 work() 方法使用。
|
||||
|
||||
ע<EFBFBD> gender <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͽ<EFBFBD><CDBD>д洢<D0B4><E6B4A2><EFBFBD><EFBFBD>װʹ<D7B0><CAB9><EFBFBD>û<EFBFBD>ע<EFBFBD>ⲻ<EFBFBD><E2B2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>ϸ<EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ʹ<EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD>ͻ<EFBFBD><CDBB>˴<EFBFBD><CBB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><C2BD>С<EFBFBD>
|
||||
注意到 gender 属性使用 int 数据类型进行存储,封装使得用户注意不到这种实现细节。并且在需要修改使用的数据类型时,也可以在不影响客户端代码的情况下进行。
|
||||
|
||||
```java
|
||||
public class Person {
|
||||
@ -95,25 +96,25 @@ public class Person {
|
||||
}
|
||||
```
|
||||
|
||||
## 2. <EFBFBD>̳<EFBFBD>
|
||||
## 2. 继承
|
||||
|
||||
<EFBFBD>̳<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> **is-a** <EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cat <EFBFBD><EFBFBD> Animal <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> is-a <20><>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD><CBBF>Խ<EFBFBD> Cat <20>̳<EFBFBD><CCB3><EFBFBD> Animal<61><6C><EFBFBD>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD><EFBFBD> Animal <EFBFBD><EFBFBD> private <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
继承实现了 **is-a** 关系,例如 Cat 和 Animal 就是一种 is-a 关系,因此可以将 Cat 继承自 Animal,从而获得 Animal 非 private 的属性和方法。
|
||||
|
||||
Cat <EFBFBD><EFBFBD><EFBFBD>Ե<EFBFBD><EFBFBD><EFBFBD> Animal <EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD> Animal <EFBFBD><EFBFBD><EFBFBD><EFBFBD> Cat <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ **<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>**<2A><>
|
||||
Cat 可以当做 Animal 来使用,也就是可以使用 Animal 引用 Cat 对象,这种子类转换为父类称为 **向上转型**。
|
||||
|
||||
<EFBFBD>̳<EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻ԭ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>ܹ<EFBFBD><EFBFBD>滻<EFBFBD>κ<EFBFBD><EFBFBD>䳬<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>ž<EFBFBD><EFBFBD><EFBFBD> is-a <EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
|
||||
继承应该遵循里氏替换原则:当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有 is-a 关系。
|
||||
|
||||
```java
|
||||
Animal animal = new Cat();
|
||||
```
|
||||
|
||||
## 3. <EFBFBD><EFBFBD>̬
|
||||
## 3. 多态
|
||||
|
||||
<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD>Ҫָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ָ̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
多态分为编译时多态和运行时多态。编译时多态主要指方法的重装,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。
|
||||
|
||||
<EFBFBD><EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1. <20>̳У<CCB3>2. <20><><EFBFBD>Ǹ<EFBFBD><C7B8><EFBFBD><E0B7BD><EFBFBD><EFBFBD>3. <20><><EFBFBD><EFBFBD>ת<EFBFBD>͡<EFBFBD>
|
||||
多态有三个条件:1. 继承;2. 覆盖父类方法;3. 向上转型。
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣨInstrument<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ࣺWind <EFBFBD><EFBFBD> Percussion<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> play() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> main() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ø<EFBFBD><C3B8><EFBFBD> Instrument <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Wind <EFBFBD><EFBFBD> Percussion <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Instrument <EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD> play() <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> play() <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Instrument <EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
下面的代码中,乐器类(Instrument)有两个子类:Wind 和 Percussion,它们都覆盖了 play() 方法,并且在 main() 方法中使用父类 Instrument 来引用 Wind 和 Percussion 对象。在 Instrument 引用调用 play() 方法时,会执行实际引用对象所在类的 play() 方法,而不是 Instrument 类的方法。
|
||||
|
||||
```java
|
||||
public class Instrument {
|
||||
@ -151,157 +152,157 @@ public class Music {
|
||||
|
||||
# UML
|
||||
|
||||
## 1. <EFBFBD><EFBFBD>ͼ
|
||||
## 1. 类图
|
||||
|
||||
**1.1 <EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1.1 继承相关**
|
||||
|
||||
<EFBFBD>̳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>generalize<7A><65><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>realize<7A><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ is-a <EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
|
||||
继承有两种形式: 泛化(generalize)和实现(realize),表现为 is-a 关系。
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ(generalization)
|
||||
① 泛化关系(generalization)
|
||||
|
||||
<EFBFBD>Ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м̳<EFBFBD>
|
||||
从具体类中继承
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD> ʵ<>ֹ<EFBFBD>ϵ(realize)
|
||||
② 实现关系(realize)
|
||||
|
||||
<EFBFBD>ӳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߽ӿ<EFBFBD><EFBFBD>м̳<EFBFBD>
|
||||
从抽象类或者接口中继承
|
||||
|
||||

|
||||

|
||||
|
||||
**1.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD>**
|
||||
**1.2 整体和部分**
|
||||
|
||||
<EFBFBD><EFBFBD> <20>ۺϹ<DBBA>ϵ(aggregation)
|
||||
① 聚合关系(aggregation)
|
||||
|
||||
<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD>ֲ<EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>岻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>ʾ B <EFBFBD><EFBFBD> A <EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD>
|
||||
表示整体由部分组成,但是整体和部分不是强依赖的,整体不存在了部分还是会存在。以下表示 B 由 A 组成:
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD>Ϲ<EFBFBD>ϵ(composition)
|
||||
② 组合关系(composition)
|
||||
|
||||
<EFBFBD>;ۺϲ<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>岻<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>繫˾<EFBFBD>Ͳ<EFBFBD><EFBFBD>ţ<EFBFBD><EFBFBD><EFBFBD>˾û<EFBFBD>˲<EFBFBD><EFBFBD>žͲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ<EFBFBD>˾<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھۺϹ<EFBFBD>ϵ<EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>˾û<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD>
|
||||
和聚合不同,组合中整体和部分是强依赖的,整体不存在了部分也不存在了。比如公司和部门,公司没了部门就不存在了。但是公司和员工就属于聚合关系了,因为公司没了员工还在。
|
||||
|
||||

|
||||

|
||||
|
||||
**1.3 <EFBFBD><EFBFBD><EFBFBD>ϵ**
|
||||
**1.3 相互联系**
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ(association)
|
||||
① 关联关系(association)
|
||||
|
||||
<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>־<EFBFBD>̬<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD>̵<EFBFBD>״̬<EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1 <20><> 1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD>ѧУ<D1A7><D0A3><EFBFBD><EFBFBD>һ<EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5>һ<EFBFBD><D2BB>ѧУ<D1A7><D0A3><EFBFBD><EFBFBD><EFBFBD>кܶ<D0BA>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ѧ<EFBFBD><D1A7>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ѧУ<D1A7><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD>һ<EFBFBD>Ĺ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD>ʼ֮ǰ<D6AE>Ϳ<EFBFBD><CDBF><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>
|
||||
表示不同类对象之间有关联,这是一种静态关系,与运行过程的状态无关,在最开始就可以确定。因此也可以用 1 对 1、多对 1、多对多这种关联关系来表示。比如学生和学校就是一种关联关系,一个学校可以有很多学生,但是一个学生只属于一个学校,因此这是一种多对一的关系,在运行开始之前就可以确定。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ(dependency)
|
||||
② 依赖关系(dependency)
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õġ<C3B5>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߷<EFBFBD><DFB7><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>롣˫<EBA1A3><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱһ<CAB1>ֲ<EFBFBD><D6B2>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>ơ<EFBFBD>
|
||||
和关联关系不同的是, 依赖关系是在运行过程中起作用的。一般依赖作为类的构造器或者方法的参数传入。双向依赖时一种不好的设计。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 2. ʱ<EFBFBD><EFBFBD>ͼ
|
||||
## 2. 时序图
|
||||
|
||||
**2.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2.1 定义**
|
||||
|
||||
ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˶<EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD>䴫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ˳<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD>Ѱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
时序图描述了对象之间传递消息的时间顺序,它用来表示用例的行为顺序。它的主要作用是通过对象间的交互来描述用例(注意是对象),从而寻找类的操作。
|
||||
|
||||
**2.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮սʱ<EFBFBD><EFBFBD>ͼ**
|
||||
**2.2 赤壁之战时序图**
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±<EFBFBD>ʾʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>
|
||||
从虚线从上往下表示时间的推进。
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD>ɼ<EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
可见,通过时序图可以知道每个类具有以下操作:
|
||||
|
||||
```java
|
||||
publc class <EFBFBD><EFBFBD><EFBFBD><EFBFBD> {
|
||||
public void Ӧս();
|
||||
publc class 刘备 {
|
||||
public void 应战();
|
||||
}
|
||||
|
||||
publc class <EFBFBD><EFBFBD><EFBFBD><EFBFBD> {
|
||||
public void <EFBFBD>ⶨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>();
|
||||
public void <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ();
|
||||
private void <EFBFBD>趫<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>();
|
||||
publc class 孔明 {
|
||||
public void 拟定策略();
|
||||
public void 联合孙权();
|
||||
private void 借东风火攻();
|
||||
}
|
||||
|
||||
public class <EFBFBD><EFBFBD><EFBFBD><EFBFBD> {
|
||||
public void <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>G<EFBFBD><EFBFBD>();
|
||||
public class 关羽 {
|
||||
public void 防守荊州();
|
||||
}
|
||||
|
||||
public class <EFBFBD>ŷ<EFBFBD> {
|
||||
public void <EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>();
|
||||
public class 张飞 {
|
||||
public void 防守荆州前线();
|
||||
}
|
||||
|
||||
public class <EFBFBD><EFBFBD>Ȩ {
|
||||
public void <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>();
|
||||
public class 孙权 {
|
||||
public void 领兵相助();
|
||||
}
|
||||
```
|
||||
|
||||
**2.3 <EFBFBD>ͼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ֮<EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD>ϵ**
|
||||
**2.3 活动图、时序图之间的关系**
|
||||
|
||||
<EFBFBD>ͼʾ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>ĽǶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
活动图示从用户的角度来描述用例;
|
||||
|
||||
ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD>ǴӼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĽǶȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
时序图是从计算机的角度(对象间的交互)描述用例。
|
||||
|
||||
**2.4 <EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD>Ĺ<EFBFBD>ϵ**
|
||||
**2.4 类图与时序图的关系**
|
||||
|
||||
<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>ľ<EFBFBD>̬<EFBFBD>ṹ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD>Ķ<EFBFBD>̬<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
|
||||
类图描述系统的静态结构,时序图描述系统的动态行为。
|
||||
|
||||
**2.5 ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
**2.5 时序图的组成**
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
① 对象
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
|
||||
有三种表现形式
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD>ڻ<EFBFBD>ͼʱ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
在画图时,应该遵循以下原则:
|
||||
|
||||
1. <EFBFBD>ѽ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܵؿ<EFBFBD>£<EFBFBD><EFBFBD>
|
||||
1. 把交互频繁的对象尽可能地靠拢。
|
||||
|
||||
2. <EFBFBD>ѳ<EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߡ<EFBFBD>
|
||||
2. 把初始化整个交互活动的对象(有时是一个参与者)放置在最左边。
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
② 生命线
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴӶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ֹ
|
||||
生命线从对象的创建开始到对象销毁时终止
|
||||
|
||||

|
||||

|
||||
|
||||
<EFBFBD><EFBFBD> <20><>Ϣ
|
||||
③ 消息
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><EFBFBD><EFBFBD>ʽͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>ʵ<EFBFBD>ֵġ<EFBFBD>
|
||||
对象之间的交互式通过发送消息来实现的。
|
||||
|
||||
<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>
|
||||
消息有4种类型:
|
||||
|
||||
1\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>첽<EFBFBD><EFBFBD>
|
||||
1\. 简单消息,不区分同步异步。
|
||||
|
||||

|
||||

|
||||
|
||||
2\. ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ͣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>
|
||||
2\. 同步消息,发送消息之后需要暂停活动来等待回应。
|
||||
|
||||

|
||||

|
||||
|
||||
3\. <EFBFBD>첽<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
3\. 异步消息,发送消息之后不需要等待。
|
||||
|
||||

|
||||

|
||||
|
||||
4\. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>
|
||||
4\. 返回消息,可选。
|
||||
|
||||
<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
④ 激活
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>䴦<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>
|
||||
生命线上的方框表示激活状态,其它时间处于休眠状态。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
# <EFBFBD>ο<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
# 参考资料
|
||||
|
||||
- Java <EFBFBD><EFBFBD><EFBFBD><EFBFBD>˼<EFBFBD><EFBFBD>
|
||||
- Java 编程思想
|
||||
|
||||
- [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>SOLIDԭ<EFBFBD><EFBFBD>](http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html)
|
||||
- [面向对象设计的SOLID原则](http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html)
|
||||
|
||||
- [<EFBFBD><EFBFBD><EFBFBD><EFBFBD>UML<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization)
|
||||
- [看懂UML类图和时序图](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization)
|
||||
|
||||
- [UMLϵ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html)
|
||||
- [UML系列——时序图(顺序图)sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html)
|
||||
|
||||
- [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------<2D><>װ<EFBFBD><D7B0><EFBFBD>̳С<CCB3><D0A1><EFBFBD>̬](http://blog.csdn.net/jianyuerensheng/article/details/51602015)
|
||||
- [面向对象编程三大特性------封装、继承、多态](http://blog.csdn.net/jianyuerensheng/article/details/51602015)
|
||||
|
Reference in New Issue
Block a user