From 56a271b4337ec2f25f46bc3d79267acb7d62946d Mon Sep 17 00:00:00 2001 From: wangxujian-laixuzhui <33362969+wangxujian-laixuzhui@users.noreply.github.com> Date: Thu, 16 Aug 2018 08:49:34 +0800 Subject: [PATCH 001/136] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E4=B8=89=E7=A7=8D=E5=AE=9E=E7=8E=B0=E6=96=B9=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E6=AF=94=E8=BE=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 并发.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 9cd5955b..1a1bacc0 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -182,7 +182,10 @@ public static void main(String[] args) { mt.start(); } ``` - +## 三种实现方式的比较 +- 实现Runnable接又可以避免Java单继承特性而带来的局限;增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。 +- 继承Thread类和实现Runnable方法启动线 程都是使用start方法,然后JVM虚拟机将此线程放到就绪队列中,如果有处理机可用, 则执行run方法。 +- 实现Callable接又要实现call方法,并且线 程执行完毕后会有返回值。其他的两种都是 重写run方法,没有返回值。 ## 实现接口 VS 继承 Thread 实现接口会更好一些,因为: From c6b517553a562ecec4505f453bff14fd818e3b59 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 17 Aug 2018 21:19:16 +0800 Subject: [PATCH 002/136] auto commit --- notes/Java 容器.md | 2 +- notes/Java 并发.md | 2 + notes/Leetcode 题解.md | 180 +++++++++++------------ notes/Linux.md | 20 +-- notes/MySQL.md | 314 ++++++++++++++++++++-------------------- notes/Redis.md | 6 +- notes/数据库系统原理.md | 86 +++++------ notes/设计模式.md | 76 +++++----- notes/面向对象思想.md | 15 +- 9 files changed, 349 insertions(+), 352 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 9959e2ca..001f864c 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -742,7 +742,7 @@ new capacity : 00100000 对于一个 Key, -- 它的哈希值如果在第 6 位上为 0,那么取模得到的结果和之前一样; +- 它的哈希值如果在第 5 位上为 0,那么取模得到的结果和之前一样; - 如果为 1,那么得到的结果为原来的结果 +16。 ### 7. 扩容-计算数组容量 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 9cd5955b..d3682d33 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -168,6 +168,8 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc 同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。 +当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。 + ```java public class MyThread extends Thread { public void run() { diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 44f3d9dc..68af3cb7 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2389,8 +2389,6 @@ private void backtracking(int row) {

-dp[N] 即为所求。 - 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 ```java @@ -2468,16 +2466,6 @@ private int rob(int[] nums, int first, int last) { } ``` -**母牛生产** - -[程序员代码面试指南-P181](#) - -题目描述:假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N,求 N 年后牛的数量。 - -第 i 年成熟的牛的数量为: - -

- **信件错排** 题目描述:有 N 个 信 和 信封,它们被打乱,求错误装信方式的数量。 @@ -2491,7 +2479,15 @@ private int rob(int[] nums, int first, int last) {

-dp[N] 即为所求。 +**母牛生产** + +[程序员代码面试指南-P181](#) + +题目描述:假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N,求 N 年后牛的数量。 + +第 i 年成熟的牛的数量为: + +

### 矩阵路径 @@ -2517,10 +2513,8 @@ public int minPathSum(int[][] grid) { int[] dp = new int[n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { - if (j == 0) { - dp[j] = dp[j]; // 只能从上侧走到该位置 - } else if (i == 0) { - dp[j] = dp[j - 1]; // 只能从左侧走到该位置 + if (i == 0) { + dp[j] = dp[j - 1]; } else { dp[j] = Math.min(dp[j - 1], dp[j]); } @@ -2584,17 +2578,18 @@ sumRange(0, 5) -> -3 ```java class NumArray { + private int[] sums; public NumArray(int[] nums) { - sums = new int[nums.length]; - for (int i = 0; i < nums.length; i++) { - sums[i] = i == 0 ? nums[0] : sums[i - 1] + nums[i]; + sums = new int[nums.length + 1]; + for (int i = 1; i <= nums.length; i++) { + sums[i] = sums[i - 1] + nums[i - 1]; } } public int sumRange(int i, int j) { - return i == 0 ? sums[j] : sums[j] - sums[i - 1]; + return sums[j + 1] - sums[i]; } } ``` @@ -2634,7 +2629,7 @@ return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] i dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。 -如果 A[i] - A[i - 1] == A[i - 1] - A[i - 2],表示 [A[i - 2], A[i - 1], A[i]] 是一个等差递增子区间。如果 [A[i - 3], A[i - 2], A[i - 1]] 是一个等差递增子区间,那么 [A[i - 3], A[i - 2], A[i - 1], A[i]] 也是。因此在这个条件下,dp[i] = dp[i-1] + 1。 +在 A[i] - A[i - 1] == A[i - 1] - A[i - 2] 的条件下,{A[i - 2], A[i - 1], A[i]} 是一个等差递增子区间。如果 {A[i - 3], A[i - 2], A[i - 1]} 是一个等差递增子区间,那么 {A[i - 3], A[i - 2], A[i - 1], A[i]} 也是等差递增子区间,dp[i] = dp[i-1] + 1。 ```java public int numberOfArithmeticSlices(int[] A) { @@ -2747,17 +2742,17 @@ public int numDecodings(String s) { ### 最长递增子序列 -已知一个序列 {S1, S2,...,Sn} ,取出若干数组成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个 **子序列** 。 +已知一个序列 {S1, S2,...,Sn},取出若干数组成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个 **子序列** 。 如果在子序列中,当下标 ix > iy 时,Six > Siy,称子序列为原序列的一个 **递增子序列** 。 -定义一个数组 dp 存储最长递增子序列的长度,dp[n] 表示以 Sn 结尾的序列的最长递增子序列长度。对于一个递增子序列 {Si1, Si2,...,Sim},如果 im < n 并且 Sim < Sn ,此时 {Si1, Si2,..., Sim, Sn} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中,长度最长的那个递增子序列就是要找的,在长度最长的递增子序列上加上 Sn 就构成了以 Sn 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | Si < Sn && i < n} 。 +定义一个数组 dp 存储最长递增子序列的长度,dp[n] 表示以 Sn 结尾的序列的最长递增子序列长度。对于一个递增子序列 {Si1, Si2,...,Sim},如果 im < n 并且 Sim < Sn,此时 {Si1, Si2,..., Sim, Sn} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中,长度最长的那个递增子序列就是要找的,在长度最长的递增子序列上加上 Sn 就构成了以 Sn 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | Si < Sn && i < n} 。 因为在求 dp[n] 时可能无法找到一个满足条件的递增子序列,此时 {Sn} 就构成了递增子序列,需要对前面的求解方程做修改,令 dp[n] 最小为 1,即:

-对于一个长度为 N 的序列,最长递增子序列并不一定会以 SN 为结尾,因此 dp[N] 不是序列的最长递增子序列的长度,需要遍历 dp 数组找出最大值才是所要的结果,即 max{ dp[i] | 1 <= i <= N} 即为所求。 +对于一个长度为 N 的序列,最长递增子序列并不一定会以 SN 为结尾,因此 dp[N] 不是序列的最长递增子序列的长度,需要遍历 dp 数组找出最大值才是所要的结果,max{ dp[i] | 1 <= i <= N} 即为所求。 **最长递增子序列** @@ -2790,7 +2785,7 @@ for (int i = 0; i < n; i++) { return ret; ``` -以上解法的时间复杂度为 O(N2) ,可以使用二分查找将时间复杂度降低为 O(NlogN)。 +以上解法的时间复杂度为 O(N2),可以使用二分查找将时间复杂度降低为 O(NlogN)。 定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素。对于一个元素 x, @@ -2915,19 +2910,19 @@ public int wiggleMaxLength(int[] nums) { 定义一个二维数组 dp 用来存储最长公共子序列的长度,其中 dp[i][j] 表示 S1 的前 i 个字符与 S2 的前 j 个字符最长公共子序列的长度。考虑 S1i 与 S2j 值是否相等,分为两种情况: -- 当 S1i==S2j 时,那么就能在 S1 的前 i-1 个字符与 S2 的前 j-1 个字符最长公共子序列的基础上再加上 S1i 这个值,最长公共子序列长度加 1 ,即 dp[i][j] = dp[i-1][j-1] + 1。 -- 当 S1i != S2j 时,此时最长公共子序列为 S1 的前 i-1 个字符和 S2 的前 j 个字符最长公共子序列,与 S1 的前 i 个字符和 S2 的前 j-1 个字符最长公共子序列,它们的最大者,即 dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }。 +- 当 S1i==S2j 时,那么就能在 S1 的前 i-1 个字符与 S2 的前 j-1 个字符最长公共子序列的基础上再加上 S1i 这个值,最长公共子序列长度加 1,即 dp[i][j] = dp[i-1][j-1] + 1。 +- 当 S1i != S2j 时,此时最长公共子序列为 S1 的前 i-1 个字符和 S2 的前 j 个字符最长公共子序列,或者 S1 的前 i 个字符和 S2 的前 j-1 个字符最长公共子序列,取它们的最大者,即 dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }。 综上,最长公共子序列的状态转移方程为:

-对于长度为 N 的序列 S1 和 长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。 +对于长度为 N 的序列 S1 和长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。 与最长递增子序列相比,最长公共子序列有以下不同点: - 针对的是两个序列,求它们的最长公共子序列。 -- 在最长递增子序列中,dp[i] 表示以 Si 为结尾的最长递增子序列长度,子序列必须包含 Si ;在最长公共子序列中,dp[i][j] 表示 S1 中前 i 个字符与 S2 中前 j 个字符的最长公共子序列长度,不一定包含 S1i 和 S2j 。 +- 在最长递增子序列中,dp[i] 表示以 Si 为结尾的最长递增子序列长度,子序列必须包含 Si ;在最长公共子序列中,dp[i][j] 表示 S1 中前 i 个字符与 S2 中前 j 个字符的最长公共子序列长度,不一定包含 S1i 和 S2j。 - 在求最终解时,最长公共子序列中 dp[N][M] 就是最终解,而最长递增子序列中 dp[N] 不是最终解,因为以 SN 为结尾的最长递增子序列不一定是整个序列最长递增子序列,需要遍历一遍 dp 数组找到最大者。 ```java @@ -2956,9 +2951,7 @@ public int lengthOfLCS(int[] nums1, int[] nums2) { - 第 i 件物品没添加到背包,总体积不超过 j 的前 i 件物品的最大价值就是总体积不超过 j 的前 i-1 件物品的最大价值,dp[i][j] = dp[i-1][j]。 - 第 i 件物品添加到背包中,dp[i][j] = dp[i-1][j-w] + v。 -第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。 - -综上,0-1 背包的状态转移方程为: +第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。因此,0-1 背包的状态转移方程为:

@@ -2981,11 +2974,11 @@ public int knapsack(int W, int N, int[] weights, int[] values) { **空间优化** -在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道,前 i 件物品的状态仅由前 i-1 件物品的状态有关,因此可以将 dp 定义为一维数组,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时, +在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道,前 i 件物品的状态仅与前 i-1 件物品的状态有关,因此可以将 dp 定义为一维数组,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时,

-因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],以防止将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。 +因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],以防将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。 ```java public int knapsack(int W, int N, int[] weights, int[] values) { @@ -3205,7 +3198,7 @@ public int findMaxForm(String[] strs, int m, int n) { } ``` -**找零钱的方法数** +**找零钱的最少硬币数** [322. Coin Change (Medium)](https://leetcode.com/problems/coin-change/description/) @@ -3286,60 +3279,6 @@ public int combinationSum4(int[] nums, int target) { } ``` -**只能进行 k 次的股票交易** - -[188. Best Time to Buy and Sell Stock IV (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) - -```java -public int maxProfit(int k, int[] prices) { - int n = prices.length; - if (k >= n / 2) { // 这种情况下该问题退化为普通的股票交易问题 - int maxProfit = 0; - for (int i = 1; i < n; i++) { - if (prices[i] > prices[i - 1]) { - maxProfit += prices[i] - prices[i - 1]; - } - } - return maxProfit; - } - int[][] maxProfit = new int[k + 1][n]; - for (int i = 1; i <= k; i++) { - int localMax = maxProfit[i - 1][0] - prices[0]; - for (int j = 1; j < n; j++) { - maxProfit[i][j] = Math.max(maxProfit[i][j - 1], prices[j] + localMax); - localMax = Math.max(localMax, maxProfit[i - 1][j] - prices[j]); - } - } - return maxProfit[k][n - 1]; -} -``` - -**只能进行两次的股票交易** - -[123. Best Time to Buy and Sell Stock III (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) - -```java -public int maxProfit(int[] prices) { - int firstBuy = Integer.MIN_VALUE, firstSell = 0; - int secondBuy = Integer.MIN_VALUE, secondSell = 0; - for (int curPrice : prices) { - if (firstBuy < -curPrice) { - firstBuy = -curPrice; - } - if (firstSell < firstBuy + curPrice) { - firstSell = firstBuy + curPrice; - } - if (secondBuy < firstSell - curPrice) { - secondBuy = firstSell - curPrice; - } - if (secondSell < secondBuy + curPrice) { - secondSell = secondBuy + curPrice; - } - } - return secondSell; -} -``` - ### 股票交易 **需要冷却期的股票交易** @@ -3432,6 +3371,60 @@ public int maxProfit(int[] prices) { } ``` +**只能进行两次的股票交易** + +[123. Best Time to Buy and Sell Stock III (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) + +```java +public int maxProfit(int[] prices) { + int firstBuy = Integer.MIN_VALUE, firstSell = 0; + int secondBuy = Integer.MIN_VALUE, secondSell = 0; + for (int curPrice : prices) { + if (firstBuy < -curPrice) { + firstBuy = -curPrice; + } + if (firstSell < firstBuy + curPrice) { + firstSell = firstBuy + curPrice; + } + if (secondBuy < firstSell - curPrice) { + secondBuy = firstSell - curPrice; + } + if (secondSell < secondBuy + curPrice) { + secondSell = secondBuy + curPrice; + } + } + return secondSell; +} +``` + +**只能进行 k 次的股票交易** + +[188. Best Time to Buy and Sell Stock IV (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) + +```java +public int maxProfit(int k, int[] prices) { + int n = prices.length; + if (k >= n / 2) { // 这种情况下该问题退化为普通的股票交易问题 + int maxProfit = 0; + for (int i = 1; i < n; i++) { + if (prices[i] > prices[i - 1]) { + maxProfit += prices[i] - prices[i - 1]; + } + } + return maxProfit; + } + int[][] maxProfit = new int[k + 1][n]; + for (int i = 1; i <= k; i++) { + int localMax = maxProfit[i - 1][0] - prices[0]; + for (int j = 1; j < n; j++) { + maxProfit[i][j] = Math.max(maxProfit[i][j - 1], prices[j] + localMax); + localMax = Math.max(localMax, maxProfit[i - 1][j] - prices[j]); + } + } + return maxProfit[k][n - 1]; +} +``` + ### 字符串编辑 **删除两个字符串的字符使它们相等** @@ -3450,11 +3443,8 @@ Explanation: You need one step to make "sea" to "ea" and another step to make "e public int minDistance(String word1, String word2) { int m = word1.length(), n = word2.length(); int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; i++) { - for (int j = 0; j <= n; j++) { - if (i == 0 || j == 0) { - continue; - } + for (int i = 1; i <= m; i++) { + for (int j = 1; j <= n; j++) { if (word1.charAt(i - 1) == word2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { diff --git a/notes/Linux.md b/notes/Linux.md index 14d3b317..8ff3e2c6 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -129,15 +129,16 @@ info 与 man 类似,但是 info 将文档分成一个个页面,每个页面 /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin ``` -env 命令可以获取当前终端的环境变量。 - ## sudo sudo 允许一般用户使用 root 可执行的命令,不过只有在 /etc/sudoers 配置文件中添加的用户才能使用该指令。 ## 包管理工具 -RPM 和 DPKG 为最常见的两类软件包管理工具。RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,随后被 GNU 开源操作系统接受并成为很多 Linux 系统 (RHEL) 的既定软件标准。与 RPM 进行竞争的是基于 Debian 操作系统 (UBUNTU) 的 DEB 软件包管理工具 DPKG,全称为 Debian Package,功能方面与 RPM 相似。 +RPM 和 DPKG 为最常见的两类软件包管理工具: + +- RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,随后被 GNU 开源操作系统接受并成为很多 Linux 系统 (RHEL) 的既定软件标准。 +- 与 RPM 进行竞争的是基于 Debian 操作系统 (Ubuntu) 的 DEB 软件包管理工具 DPKG,全称为 Debian Package,功能方面与 RPM 相似。 YUM 基于 RPM,具有依赖管理功能,并具有软件升级的功能。 @@ -194,13 +195,13 @@ IDE(ATA)全称 Advanced Technology Attachment,接口速度最大为 133MB/ ### 2. SATA -SATA 全称 Serial ATA,也就是使用串口的 ATA 接口,因抗干扰性强,且对数据线的长度要求比 ATA 低很多,支持热插拔等功能,SATA-II 的接口速度为 300MiB/s,而新的 SATA-III 标准可达到 600MiB/s 的传输速度。SATA 的数据线也比 ATA 的细得多,有利于机箱内的空气流通,整理线材也比较方便。 +SATA 全称 Serial ATA,也就是使用串口的 ATA 接口,抗干扰性强,且对数据线的长度要求比 ATA 低很多,支持热插拔等功能。SATA-II 的接口速度为 300MiB/s,而新的 SATA-III 标准可达到 600MiB/s 的传输速度。SATA 的数据线也比 ATA 的细得多,有利于机箱内的空气流通,整理线材也比较方便。

### 3. SCSI -SCSI 全称是 Small Computer System Interface(小型机系统接口),经历多代的发展,从早期的 SCSI-II,到目前的 Ultra320 SCSI 以及 Fiber-Channel(光纤通道),接口型式也多种多样。SCSI 硬盘广为工作站级个人电脑以及服务器所使用,因此会使用较为先进的技术,如碟片转速 15000rpm 的高转速,且资料传输时 CPU 占用率较低,但是单价也比相同容量的 ATA 及 SATA 硬盘更加昂贵。 +SCSI 全称是 Small Computer System Interface(小型机系统接口),经历多代的发展,从早期的 SCSI-II 到目前的 Ultra320 SCSI 以及 Fiber-Channel(光纤通道),接口型式也多种多样。SCSI 硬盘广为工作站级个人电脑以及服务器所使用,因此会使用较为先进的技术,如碟片转速 15000rpm 的高转速,且传输时 CPU 占用率较低,但是单价也比相同容量的 ATA 及 SATA 硬盘更加昂贵。

@@ -229,7 +230,7 @@ Linux 中每个硬件都被当做一个文件,包括磁盘。磁盘以磁盘 MBR 中,第一个扇区最重要,里面有主要开机记录(Master boot record, MBR)及分区表(partition table),其中主要开机记录占 446 bytes,分区表占 64 bytes。 -分区表只有 64 bytes,最多只能存储 4 个分区,这 4 个分区为主分区(Primary)和扩展分区(Extended)。其中扩展分区只有一个,它将其它扇区用来记录分区表,因此通过扩展分区可以分出更多分区,这些分区称为逻辑分区。 +分区表只有 64 bytes,最多只能存储 4 个分区,这 4 个分区为主分区(Primary)和扩展分区(Extended)。其中扩展分区只有一个,它使用其它扇区用记录额外的分区表,因此通过扩展分区可以分出更多分区,这些分区称为逻辑分区。 Linux 也把分区当成文件,分区文件的命名方式为:磁盘文件名 + 编号,例如 /dev/sda1。注意,逻辑分区的编号从 5 开始。 @@ -251,10 +252,10 @@ MBR 不支持 2.2 TB 以上的硬盘,GPT 则最多支持到 233 TB BIOS(Basic Input/Output System,基本输入输出系统),它是一个固件(嵌入在硬件中的软件),BIOS 程序存放在断电后内容不会丢失的只读内存中。 -BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可以开机的磁盘,并读取磁盘第一个扇区的主要开机记录(MBR),由主要开机记录(MBR)执行其中的开机管理程序,这个开机管理程序会加载操作系统的核心文件。 -

+BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可以开机的磁盘,并读取磁盘第一个扇区的主要开机记录(MBR),由主要开机记录(MBR)执行其中的开机管理程序,这个开机管理程序会加载操作系统的核心文件。 + 主要开机记录(MBR)中的开机管理程序提供以下功能:选单、载入核心文件以及转交其它开机管理程序。转交这个功能可以用来实现了多重引导,只需要将另一个操作系统的开机管理程序安装在其它分区的启动扇区上,在启动开机管理程序时,就可以通过选单选择启动当前的操作系统或者转交给其它开机管理程序从而启动另一个操作系统。 下图中,第一扇区的主要开机记录(MBR)中的开机管理程序提供了两个选单:M1、M2,M1 指向了 Windows 操作系统,而 M2 指向其它分区的启动扇区,里面包含了另外一个开机管理程序,提供了一个指向 Linux 的选单。 @@ -283,11 +284,10 @@ BIOS 不可以读取 GPT 分区表,而 UEFI 可以。 除此之外还包括: - superblock:记录文件系统的整体信息,包括 inode 和 block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等; -- block bitmap:记录 block 是否被使用的位域; +- block bitmap:记录 block 是否被使用的位域。

- ## 文件读取 对于 Ext2 文件系统,当要读取一个文件的内容时,先在 inode 中去查找文件内容所在的所有 block,然后把所有 block 的内容读出来。 diff --git a/notes/MySQL.md b/notes/MySQL.md index 7ac9685f..54067977 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -1,22 +1,23 @@ -* [一、存储引擎](#一存储引擎) +* [一、索引](#一索引) + * [B+ Tree 原理](#b-tree-原理) + * [MySQL 索引](#mysql-索引) + * [索引优化](#索引优化) + * [索引的优点](#索引的优点) + * [索引的使用场景](#索引的使用场景) +* [二、查询性能优化](#二查询性能优化) + * [使用 Explain 进行分析](#使用-explain-进行分析) + * [优化数据访问](#优化数据访问) + * [重构查询方式](#重构查询方式) +* [三、存储引擎](#三存储引擎) * [InnoDB](#innodb) * [MyISAM](#myisam) * [比较](#比较) -* [二、数据类型](#二数据类型) +* [四、数据类型](#四数据类型) * [整型](#整型) * [浮点数](#浮点数) * [字符串](#字符串) * [时间和日期](#时间和日期) -* [三、索引](#三索引) - * [B+ Tree 原理](#b-tree-原理) - * [索引分类](#索引分类) - * [索引的优点](#索引的优点) - * [索引优化](#索引优化) -* [四、查询性能优化](#四查询性能优化) - * [使用 Explain 进行分析](#使用-explain-进行分析) - * [优化数据访问](#优化数据访问) - * [重构查询方式](#重构查询方式) * [五、切分](#五切分) * [水平切分](#水平切分) * [垂直切分](#垂直切分) @@ -29,101 +30,7 @@ -# 一、存储引擎 - -## InnoDB - -InnoDB 是 MySQL 默认的事务型存储引擎,只有在需要 InnoDB 不支持的特性时,才考虑使用其它存储引擎。 - -实现了四个标准的隔离级别,默认级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,通过多版本并发控制(MVCC)+ 间隙锁(next-key locking)防止幻影读。 - -主索引是聚簇索引,在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。 - -内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。 - -支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。 - -## MyISAM - -MyISAM 设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用 MyISAM。 - -MyISAM 提供了大量的特性,包括压缩表、空间数据索引等。 - -不支持事务。 - -不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。 - -可以手工或者自动执行检查和修复操作,但是和事务恢复以及崩溃恢复不同,可能导致一些数据丢失,而且修复操作是非常慢的。 - -如果指定了 DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立即将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘。这种方式可以极大的提升写入性能,但是在数据库或者主机崩溃时会造成索引损坏,需要执行修复操作。 - -## 比较 - -- 事务:InnoDB 是事务型的,可以使用 Commit 和 Rollback 语句。 - -- 并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。 - -- 外键:InnoDB 支持外键。 - -- 备份:InnoDB 支持在线热备份。 - -- 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。 - -- 其它特性:MyISAM 支持压缩表和空间数据索引。 - -# 二、数据类型 - -## 整型 - -TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT 分别使用 8, 16, 24, 32, 64 位存储空间,一般情况下越小的列越好。 - -INT(11) 中的数字只是规定了交互工具显示字符的个数,对于存储和计算来说是没有意义的。 - -## 浮点数 - -FLOAT 和 DOUBLE 为浮点类型,DECIMAL 为高精度小数类型。CPU 原生支持浮点运算,但是不支持 DECIMAl 类型的计算,因此 DECIMAL 的计算比浮点类型需要更高的代价。 - -FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示总共 18 位,取 9 位存储小数部分,剩下 9 位存储整数部分。 - -## 字符串 - -主要有 CHAR 和 VARCHAR 两种类型,一种是定长的,一种是变长的。 - -VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。 - -VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。 - -## 时间和日期 - -MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。 - -### 1. DATETIME - -能够保存从 1001 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。 - -它与时区无关。 - -默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATETIME 值,例如“2008-01-16 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。 - -### 2. TIMESTAMP - -和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。 - -它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。 - -MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提供了 UNIX_TIMESTAMP() 函数把日期转换为 UNIX 时间戳。 - -默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。 - -应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。 - -# 三、索引 - -索引能够轻易将查询性能提升几个数量级。 - -对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。对于中到大型的表,索引就非常有效。但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。 - -索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。 +# 一、索引 ## B+ Tree 原理 @@ -141,37 +48,37 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具 进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。 -插入删除操作记录会破坏平衡树的平衡性,因此在插入删除时,需要对树进行一个分裂、合并、旋转等操作。 +插入删除操作记录会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。 ### 3. 与红黑树的比较 红黑树等平衡树也可以用来实现索引,但是文件系统及数据库系统普遍采用 B+ Tree 作为索引结构,主要有以下两个原因: -(一)更少的检索次数 +(一)更少的查找次数 -平衡树检索数据的时间复杂度等于树高 h,而树高大致为 O(h)=O(logdN),其中 d 为每个节点的出度。 +平衡树查找操作的时间复杂度等于树高 h,而树高大致为 O(h)=O(logdN),其中 d 为每个节点的出度。 -红黑树的出度为 2,而 B+ Tree 的出度一般都非常大。红黑树的树高 h 很明显比 B+ Tree 大非常多,因此检索的次数也就更多。 +红黑树的出度为 2,而 B+ Tree 的出度一般都非常大,所以红黑树的树高 h 很明显比 B+ Tree 大非常多,检索的次数也就更多。 (二)利用计算机预读特性 -为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道,并且只需要很短的旋转时间,因此速度会非常快。 +为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道,并且只需要很短的旋转时间,因此速度会非常快。 操作系统一般将内存和磁盘分割成固态大小的块,每一块称为一页,内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小,使得一次 I/O 就能完全载入一个节点,并且可以利用预读特性,相邻的节点也能够被预先载入。 -## 索引分类 +## MySQL 索引 + +索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。 ### 1. B+Tree 索引 -B+Tree 索引是大多数 MySQL 存储引擎的默认索引类型。 +是大多数 MySQL 存储引擎的默认索引类型。 因为不再需要进行全表扫描,只需要对树进行搜索即可,因此查找速度快很多。除了用于查找,还可以用于排序和分组。 可以指定多个列作为索引列,多个索引列共同组成键。 -B+Tree 索引适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。 - -如果不是按照索引列的顺序进行查找,则无法使用索引。 +适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。如果不是按照索引列的顺序进行查找,则无法使用索引。 InnoDB 的 B+Tree 索引分为主索引和辅助索引。 @@ -185,12 +92,12 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。 ### 2. 哈希索引 -InnoDB 引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。 - 哈希索引能以 O(1) 时间进行查找,但是失去了有序性,它具有以下限制: - 无法用于排序与分组; -- 只支持精确查找,无法用于部分查找和范围查找; +- 只支持精确查找,无法用于部分查找和范围查找。 + +InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。 ### 3. 全文索引 @@ -200,20 +107,12 @@ MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而 InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引。 -### 4. 空间数据索引(R-Tree) +### 4. 空间数据索引 -MyISAM 存储引擎支持空间数据索引,可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。 +MyISAM 存储引擎支持空间数据索引(R-Tree),可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。 必须使用 GIS 相关的函数来维护数据。 -## 索引的优点 - -- 大大减少了服务器需要扫描的数据行数。 - -- 帮助服务器避免进行排序和创建临时表(B+Tree 索引是有序的,可以用来做 ORDER BY 和 GROUP BY 操作); - -- 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,也就将相邻的数据都存储在一起)。 - ## 索引优化 ### 1. 独立的列 @@ -266,11 +165,25 @@ customer_id_selectivity: 0.0373 具有以下优点: -- 因为索引条目通常远小于数据行的大小,所以若只读取索引,能大大减少数据访问量。 +- 索引通常远小于数据行的大小,只读取索引能大大减少数据访问量。 - 一些存储引擎(例如 MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。 - 对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。 -# 四、查询性能优化 +## 索引的优点 + +- 大大减少了服务器需要扫描的数据行数。 + +- 帮助服务器避免进行排序和分组,也就不需要创建临时表(B+Tree 索引是有序的,可以用于 ORDER BY 和 GROUP BY 操作。临时表主要是在排序和分组过程中创建,因为不需要排序和分组,也就不需要创建临时表)。 + +- 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,也就将相邻的数据都存储在一起)。 + +## 索引的使用场景 + +- 对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。 +- 对于中到大型的表,索引就非常有效。 +- 但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。 + +# 二、查询性能优化 ## 使用 Explain 进行分析 @@ -282,23 +195,13 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai - key : 使用的索引 - rows : 扫描的行数 -更多内容请参考:[MySQL 性能优化神器 Explain 使用分析](https://segmentfault.com/a/1190000008131735) - ## 优化数据访问 ### 1. 减少请求的数据量 -(一)只返回必要的列 - -最好不要使用 SELECT * 语句。 - -(二)只返回必要的行 - -使用 WHERE 语句进行查询过滤,有时候也需要使用 LIMIT 语句来限制返回的数据。 - -(三)缓存重复查询的数据 - -使用缓存可以避免在数据库中进行查询,特别要查询的数据经常被重复查询,缓存可以带来的查询性能提升将会是非常明显的。 +- 只返回必要的列:最好不要使用 SELECT * 语句。 +- 只返回必要的行:使用 LIMIT 语句来限制返回的数据。 +- 缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的。 ### 2. 减少服务器端扫描的行数 @@ -324,12 +227,12 @@ do { ### 2. 分解大连接查询 -将一个大连接查询(JOIN)分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有: +将一个大连接查询分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有: - 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。 - 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。 - 减少锁竞争; -- 在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可扩展。 +- 在应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可伸缩。 - 查询本身效率也可能会有所提升。例如下面的例子中,使用 IN() 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。 ```sql @@ -345,23 +248,111 @@ SELECT * FROM tag_post WHERE tag_id=1234; SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904); ``` +# 三、存储引擎 + +## InnoDB + +是 MySQL 默认的事务型存储引擎,只有在需要它不支持的特性时,才考虑使用其它存储引擎。 + +实现了四个标准的隔离级别,默认级别是可重复读(REPEATABLE READ)。在可重复读隔离级别下,通过多版本并发控制(MVCC)+ 间隙锁(Next-Key Locking)防止幻影读。 + +主索引是聚簇索引,在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。 + +内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。 + +支持真正的在线热备份。其它存储引擎不支持在线热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能也意味着停止读取。 + +## MyISAM + +设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用它。 + +提供了大量的特性,包括压缩表、空间数据索引等。 + +不支持事务。 + +不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。 + +可以手工或者自动执行检查和修复操作,但是和事务恢复以及崩溃恢复不同,可能导致一些数据丢失,而且修复操作是非常慢的。 + +如果指定了 DELAY_KEY_WRITE 选项,在每次修改执行完成时,不会立即将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区,只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入磁盘。这种方式可以极大的提升写入性能,但是在数据库或者主机崩溃时会造成索引损坏,需要执行修复操作。 + +## 比较 + +- 事务:InnoDB 是事务型的,可以使用 Commit 和 Rollback 语句。 + +- 并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。 + +- 外键:InnoDB 支持外键。 + +- 备份:InnoDB 支持在线热备份。 + +- 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。 + +- 其它特性:MyISAM 支持压缩表和空间数据索引。 + +# 四、数据类型 + +## 整型 + +TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT 分别使用 8, 16, 24, 32, 64 位存储空间,一般情况下越小的列越好。 + +INT(11) 中的数字只是规定了交互工具显示字符的个数,对于存储和计算来说是没有意义的。 + +## 浮点数 + +FLOAT 和 DOUBLE 为浮点类型,DECIMAL 为高精度小数类型。CPU 原生支持浮点运算,但是不支持 DECIMAl 类型的计算,因此 DECIMAL 的计算比浮点类型需要更高的代价。 + +FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示总共 18 位,取 9 位存储小数部分,剩下 9 位存储整数部分。 + +## 字符串 + +主要有 CHAR 和 VARCHAR 两种类型,一种是定长的,一种是变长的。 + +VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。 + +VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。 + +## 时间和日期 + +MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。 + +### 1. DATETIME + +能够保存从 1001 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。 + +它与时区无关。 + +默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATETIME 值,例如“2008-01-16 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。 + +### 2. TIMESTAMP + +和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。 + +它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。 + +MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提供了 UNIX_TIMESTAMP() 函数把日期转换为 UNIX 时间戳。 + +默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。 + +应该尽量使用 TIMESTAMP,因为它比 DATETIME 空间效率更高。 + # 五、切分 ## 水平切分 -

- 水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。 当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓存单个数据库的压力。 +

+ ## 垂直切分

垂直切分是将一张表按列切分成多个表,通常是按照列的关系密集程度进行切分,也可以利用垂直切分将经常被使用的列和不经常被使用的列切分到不同的表中。 -在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库 payDB、用户数据库 userDB 等。 +在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库、用户数据库等。 ## Sharding 策略 @@ -375,15 +366,15 @@ SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904); 使用分布式事务来解决,比如 XA 接口。 -### 2. JOIN +### 2. 链接 -可以将原来的 JOIN 查询分解成多个单表查询,然后在用户程序中进行 JOIN。 +可以将原来的 JOIN 分解成多个单表查询,然后在用户程序中进行 JOIN。 ### 3. ID 唯一性 -- 使用全局唯一 ID:GUID。 -- 为每个分片指定一个 ID 范围。 -- 分布式 ID 生成器 (如 Twitter 的 Snowflake 算法)。 +- 使用全局唯一 ID:GUID +- 为每个分片指定一个 ID 范围 +- 分布式 ID 生成器 (如 Twitter 的 Snowflake 算法) 更多内容请参考: @@ -396,24 +387,24 @@ SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904); 主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。 -- **binlog 线程** :负责将主服务器上的数据更改写入二进制文件(binlog)中。 -- **I/O 线程** :负责从主服务器上读取二进制日志文件,并写入从服务器的中继日志中。 +- **binlog 线程** :负责将主服务器上的数据更改写入二进制日志中。 +- **I/O 线程** :负责从主服务器上读取二进制日志,并写入从服务器的中继日志中。 - **SQL 线程** :负责读取中继日志并重放其中的 SQL 语句。

## 读写分离 -主服务器用来处理写操作以及实时性要求比较高的读操作,而从服务器用来处理读操作。 +主服务器处理写操作以及实时性要求比较高的读操作,而从服务器处理读操作。 -读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。 - -MySQL 读写分离能提高性能的原因在于: +读写分离能提高性能的原因在于: - 主从服务器负责各自的读和写,极大程度缓解了锁的争用; -- 从服务器可以配置 MyISAM 引擎,提升查询性能以及节约系统开销; +- 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销; - 增加冗余,提高可用性。 +读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。 +

# 参考资料 @@ -425,3 +416,4 @@ MySQL 读写分离能提高性能的原因在于: - [How to create unique row ID in sharded databases?](https://stackoverflow.com/questions/788829/how-to-create-unique-row-id-in-sharded-databases) - [SQL Azure Federation – Introduction](http://geekswithblogs.net/shaunxu/archive/2012/01/07/sql-azure-federation-ndash-introduction.aspx "Title of this entry.") - [MySQL 索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html) +- [MySQL 性能优化神器 Explain 使用分析](https://segmentfault.com/a/1190000008131735) diff --git a/notes/Redis.md b/notes/Redis.md index 0981abf0..8f231382 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -49,7 +49,7 @@ Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 -键的类型只能为字符串,值支持的五种类型数据类型为:字符串、列表、集合、有序集合、散列表。 +键的类型只能为字符串,值支持的五种类型数据类型为:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。 @@ -58,7 +58,7 @@ Redis 支持很多特性,例如将内存中的数据持久化到硬盘中, | 数据类型 | 可以存储的值 | 操作 | | :--: | :--: | :--: | | STRING | 字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作
对整数和浮点数执行自增或者自减操作 | -| LIST | 列表 | 从两端压入或者弹出元素
读取单个或者多个元素
进行修剪,只保留一个范围内的元素 | +| LIST | 列表 | 从两端压入或者弹出元素
对单个或者多个元素
进行修剪,只保留一个范围内的元素 | | SET | 无序集合 | 添加、获取、移除单个元素
检查一个元素是否存在于集合中
计算交集、并集、差集
从集合里面随机获取元素 | | HASH | 包含键值对的无序散列表 | 添加、获取、移除单个键值对
获取所有键值对
检查某个键是否存在| | ZSET | 有序集合 | 添加、获取、删除元素
根据分值范围或者成员来获取元素
计算一个键的排名 | @@ -555,7 +555,7 @@ Sentinel(哨兵)可以监听主服务器,并在主服务器进入下线状 分片是将数据划分为多个部分的方法,可以将数据存储到多台机器里面,这种方法在解决某些问题时可以获得线性级别的性能提升。 -假设有 4 个 Reids 实例 R0,R1,R2,R3,还有很多表示用户的键 user:1,user:2,... 等等,有不同的方式来选择一个指定的键存储在哪个实例中。 +假设有 4 个 Reids 实例 R0,R1,R2,R3,还有很多表示用户的键 user:1,user:2,... ,有不同的方式来选择一个指定的键存储在哪个实例中。 - 最简单的方式是范围分片,例如用户 id 从 0\~1000 的存储到实例 R0 中,用户 id 从 1001\~2000 的存储到实例 R1 中,等等。但是这样需要维护一张映射范围表,维护操作代价很高。 - 还有一种方式是哈希分片,使用 CRC32 哈希函数将键转换为一个数字,再对实例数量求模就能知道应该存储的实例。 diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index e7ef804b..1bcd2533 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -20,6 +20,7 @@ * [可串行化(SERIALIZABLE)](#可串行化serializable) * [五、多版本并发控制](#五多版本并发控制) * [版本号](#版本号) + * [隐藏的列](#隐藏的列) * [Undo 日志](#undo-日志) * [实现过程](#实现过程) * [快照读与当前读](#快照读与当前读) @@ -58,9 +59,7 @@ ### 2. 一致性(Consistency) -数据库在事务执行前后都保持一致性状态。 - -在一致性状态下,所有事务对一个数据的读取结果都是相同的。 +数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。 ### 3. 隔离性(Isolation) @@ -78,10 +77,10 @@ - 只有满足一致性,事务的执行结果才是正确的。 - 在无并发的情况下,事务串行执行,隔离性一定能够满足。此时只要能满足原子性,就一定能满足一致性。 -- 在并发的情况下,多个事务并发执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。 +- 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。 - 事务满足持久化是为了能应对数据库崩溃的情况。 -

+

## AUTOCOMMIT @@ -95,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。 -

+

## 读脏数据 T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。 -

+

## 不可重复读 T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。 -

+

## 幻影读 T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。 -

+

---- @@ -123,7 +122,6 @@ T1 读取某个范围的数据,T2 在这个范围内插 ## 封锁粒度 - MySQL 中提供了两种封锁粒度:行级锁以及表级锁。 应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能就越小,系统的并发程度就越高。 @@ -150,8 +148,8 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。 | - | X | S | | :--: | :--: | :--: | -|X|NO|NO| -|S|NO|YES| +|X|×|×| +|S|×|√| ### 2. 意向锁 @@ -170,10 +168,10 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。 | - | X | IX | S | IS | | :--: | :--: | :--: | :--: | :--: | -|X |NO |NO |NO | NO| -|IX |NO |YES |NO | YES| -|S |NO |NO |YES | YES| -|IS |NO |YES |YES | YES| +|X |× |× |× | ×| +|IX |× |√ |× | √| +|S |× |× |√ | √| +|IS |× |√ |√ | √| 解释如下: @@ -298,32 +296,30 @@ SELECT ... FOR UPDATE; | 隔离级别 | 脏读 | 不可重复读 | 幻影读 | | :---: | :---: | :---:| :---: | -| 未提交读 | YES | YES | YES | -| 提交读 | NO | YES | YES | -| 可重复读 | NO | NO | YES | -| 可串行化 | NO | NO | NO | +| 未提交读 | √ | √ | √ | +| 提交读 | × | √ | √ | +| 可重复读 | × | × | √ | +| 可串行化 | × | × | × | # 五、多版本并发控制 -多版本并发控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存储引擎实现隔离级别的一种具体方式,用于实现提交读和可重复读这两种隔离级别。 - -而未提交读隔离级别总是读取最新的数据行,无需使用 MVCC。 - -可串行化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现。 +多版本并发控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存储引擎实现隔离级别的一种具体方式,用于实现提交读和可重复读这两种隔离级别。而未提交读隔离级别总是读取最新的数据行,无需使用 MVCC。可串行化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现。 ## 版本号 - 系统版本号:是一个递增的数字,每开始一个新的事务,系统版本号就会自动递增。 - 事务版本号:事务开始时的系统版本号。 -InooDB 的 MVCC 在每行记录后面都保存着两个隐藏的列,用来存储两个版本号: +## 隐藏的列 + +MVCC 在每行记录后面都保存着两个隐藏的列,用来存储两个版本号: - 创建版本号:指示创建一个数据行的快照时的系统版本号; - 删除版本号:如果该快照的删除版本号大于当前事务版本号表示该快照有效,否则表示该快照已经被删除了。 ## Undo 日志 -InnoDB 的 MVCC 使用到的快照存储在 Undo 日志中,该日志通过回滚指针把一个数据行(Record)的所有快照连接起来。 +MVCC 使用到的快照存储在 Undo 日志中,该日志通过回滚指针把一个数据行(Record)的所有快照连接起来。

@@ -331,15 +327,13 @@ InnoDB 的 MVCC 使用到的快照存储在 Undo 日志中,该日志通过回 以下实现过程针对可重复读隔离级别。 -### 1. SELECT - 当开始新一个事务时,该事务的版本号肯定会大于当前所有数据行快照的创建版本号,理解这一点很关键。 +### 1. SELECT + 多个事务必须读取到同一个数据行的快照,并且这个快照是距离现在最近的一个有效快照。但是也有例外,如果有一个事务正在修改该数据行,那么它可以读取事务本身所做的修改,而不用和其它事务的读取结果一致。 -把没有对一个数据行做修改的事务称为 T,T 所要读取的数据行快照的创建版本号必须小于 T 的版本号,因为如果大于或者等于 T 的版本号,那么表示该数据行快照是其它事务的最新修改,因此不能去读取它。 - -除了上面的要求,T 所要读取的数据行快照的删除版本号必须大于 T 的版本号,因为如果小于等于 T 的版本号,那么表示该数据行快照是已经被删除的,不应该去读取它。 +把没有对一个数据行做修改的事务称为 T,T 所要读取的数据行快照的创建版本号必须小于 T 的版本号,因为如果大于或者等于 T 的版本号,那么表示该数据行快照是其它事务的最新修改,因此不能去读取它。除此之外,T 所要读取的数据行快照的删除版本号必须大于 T 的版本号,因为如果小于等于 T 的版本号,那么表示该数据行快照是已经被删除的,不应该去读取它。 ### 2. INSERT @@ -385,7 +379,7 @@ MVCC 不能解决幻读的问题,Next-Key Locks 就是为了解决这个问题 锁定一个记录上的索引,而不是记录本身。 -如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚集索引,因此 Record Locks 依然可以使用。 +如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。 ## Gap Locks @@ -397,7 +391,7 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE; ## Next-Key Locks -它是 Record Locks 和 Gap Locks 的结合,不仅锁定一个记录上的索引,也锁定范围内的索引。例如一个索引包含以下值:10, 11, 13, and 20,那么就需要锁定以下区间: +它是 Record Locks 和 Gap Locks 的结合,不仅锁定一个记录上的索引,也锁定索引之间的间隙。例如一个索引包含以下值:10, 11, 13, and 20,那么就需要锁定以下区间: ```sql (negative infinity, 10] @@ -432,10 +426,10 @@ SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE; 不符合范式的关系,会产生很多异常,主要有以下四种异常: -- 冗余数据:例如 学生-2 出现了两次。 +- 冗余数据:例如 `学生-2` 出现了两次。 - 修改异常:修改了一个记录中的信息,但是另一个记录中相同的信息却没有被修改。 -- 删除异常:删除一个信息,那么也会丢失其它信息。例如如果删除了 课程-1,需要删除第一行和第三行,那么 学生-1 的信息就会丢失。 -- 插入异常,例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。 +- 删除异常:删除一个信息,那么也会丢失其它信息。例如删除了 `课程-1` 需要删除第一行和第三行,那么 `学生-1` 的信息就会丢失。 +- 插入异常:例如想要插入一个学生的信息,如果这个学生还没选课,那么就无法插入。 ## 范式 @@ -506,7 +500,11 @@ Sname, Sdept 和 Mname 都部分依赖于键码,当一个学生选修了多门 非主属性不传递函数依赖于键码。 -上面的 关系-1 中存在以下传递函数依赖:Sno -> Sdept -> Mname,可以进行以下分解: +上面的 关系-1 中存在以下传递函数依赖: + +- Sno -> Sdept -> Mname + +可以进行以下分解: 关系-11 @@ -533,13 +531,19 @@ Entity-Relationship,有三个组成部分:实体、属性、联系。 包含一对一,一对多,多对多三种。 -如果 A 到 B 是一对多关系,那么画个带箭头的线段指向 B;如果是一对一,画两个带箭头的线段;如果是多对多,画两个不带箭头的线段。下图的 Course 和 Student 是一对多的关系。 +- 如果 A 到 B 是一对多关系,那么画个带箭头的线段指向 B; +- 如果是一对一,画两个带箭头的线段; +- 如果是多对多,画两个不带箭头的线段。 + +下图的 Course 和 Student 是一对多的关系。

## 表示出现多次的关系 -一个实体在联系出现几次,就要用几条线连接。下图表示一个课程的先修关系,先修关系出现两个 Course 实体,第一个是先修课程,后一个是后修课程,因此需要用两条线来表示这种关系。 +一个实体在联系出现几次,就要用几条线连接。 + +下图表示一个课程的先修关系,先修关系出现两个 Course 实体,第一个是先修课程,后一个是后修课程,因此需要用两条线来表示这种关系。

@@ -549,7 +553,7 @@ Entity-Relationship,有三个组成部分:实体、属性、联系。

-一般只使用二元联系,可以把多元关系转换为二元关系。 +一般只使用二元联系,可以把多元联系转换为二元联系。

diff --git a/notes/设计模式.md b/notes/设计模式.md index b8f4dc9b..531595e3 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -60,9 +60,9 @@ (一)懒汉式-线程不安全 -以下实现中,私有静态变量 uniqueInstance 被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 +以下实现中,私有静态变量 uniqueInstance 被延迟实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 -这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么多个线程会执行 `uniqueInstance = new Singleton();` 语句,这将导致多次实例化 uniqueInstance。 +这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么会有多个线程执行 `uniqueInstance = new Singleton();` 语句,这将导致多次实例化 uniqueInstance。 ```java public class Singleton { @@ -81,11 +81,21 @@ public class Singleton { } ``` -(二)懒汉式-线程安全 +(二)饿汉式-线程安全 -只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。 +线程不安全问题主要是由于 uniqueInstance 被多次实例化,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。 -但是这样有一个问题,就是当一个线程进入该方法之后,其它线程试图进入该方法都必须等待,因此性能上有一定的损耗。 +但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。 + +```java +private static Singleton uniqueInstance = new Singleton(); +``` + +(三)懒汉式-线程安全 + +只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了多次实例化 uniqueInstance 的问题。 + +但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,因此性能上有一定的损耗。 ```java public static synchronized Singleton getUniqueInstance() { @@ -96,16 +106,6 @@ public static synchronized Singleton getUniqueInstance() { } ``` -(三)饿汉式-线程安全 - -线程不安全问题主要是由于 uniqueInstance 被实例化了多次,如果 uniqueInstance 采用直接实例化的话,就不会被实例化多次,也就不会产生线程不安全问题。 - -但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。 - -```java -private static Singleton uniqueInstance = new Singleton(); -``` - (四)双重校验锁-线程安全 uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。 @@ -175,7 +175,7 @@ public class Singleton { } ``` -(五)枚举实现 +(六)枚举实现 这是单例模式的最佳实践,它实现简单,并且在面对复杂的序列化或者反射攻击的时候,能够防止实例化多次。 @@ -231,27 +231,9 @@ public class Singleton implements Serializable { 简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 -

- 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。因为客户类往往有多个,如果不使用简单工厂,所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 -如果存在下面这种代码,就需要使用简单工厂将对象实例化的部分放到简单工厂中。 - -```java -public class Client { - public static void main(String[] args) { - int type = 1; - Product product; - if (type == 1) { - product = new ConcreteProduct1(); - } else if (type == 2) { - product = new ConcreteProduct2(); - } else { - product = new ConcreteProduct(); - } - } -} -``` +

### 实现 @@ -275,6 +257,27 @@ public class ConcreteProduct2 implements Product { } ``` +以下的 Client 类中包含了实例化的代码,这是一种错误的实现,如果在客户类中存在实例化代码,就需要将代码放到简单工厂中。 + +```java +public class Client { + public static void main(String[] args) { + int type = 1; + Product product; + if (type == 1) { + product = new ConcreteProduct1(); + } else if (type == 2) { + product = new ConcreteProduct2(); + } else { + product = new ConcreteProduct(); + } + // do something with the product + } +} +``` + +以下的 SimpleFactory 是简单工厂实现,它被所有需要进行实例化的客户类调用。 + ```java public class SimpleFactory { public Product createProduct(int type) { @@ -293,6 +296,7 @@ public class Client { public static void main(String[] args) { SimpleFactory simpleFactory = new SimpleFactory(); Product product = simpleFactory.createProduct(1); + // do something with the product } } ``` @@ -2906,7 +2910,7 @@ Java 利用缓存来加速大量小对象的访问时间。 - 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。 - 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。 - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 -- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数,比如智能智能;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 +- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 9b59e43d..203c7ebf 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -37,6 +37,7 @@ ```java public class Person { + private String name; private int gender; private int age; @@ -63,17 +64,20 @@ public class Person { 继承实现了 **IS-A** 关系,例如 Cat 和 Animal 就是一种 IS-A 关系,因此 Cat 可以继承自 Animal,从而获得 Animal 非 private 的属性和方法。 +继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。 + Cat 可以当做 Animal 来使用,也就是说可以使用 Animal 引用 Cat 对象。父类引用指向子类对象称为 **向上转型** 。 ```java Animal animal = new Cat(); ``` -继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。 - ## 多态 -多态分为编译时多态和运行时多态。编译时多态主要指方法的重载,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。 +多态分为编译时多态和运行时多态: + +- 编译时多态主要指方法的重载 +- 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定 运行时多态有三个条件: @@ -116,7 +120,7 @@ public class Music { # 二、类图 -以下类图使用 [PlantUML](https://www.planttext.com/) 绘制,更多语法及使用请参考:http://plantuml.com/ +以下类图使用 [PlantUML](https://www.planttext.com/) 绘制,更多语法及使用请参考:http://plantuml.com/ 。 ## 泛化关系 (Generalization) @@ -327,7 +331,7 @@ Vihicle .. N ### 2. 合成复用原则 -尽量使用对象组合,而不是继承来达到复用的目的。 +尽量使用对象组合,而不是通过继承来达到复用的目的。 ### 3. 共同封闭原则 @@ -349,3 +353,4 @@ Vihicle .. N - [看懂 UML 类图和时序图](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization) - [UML 系列——时序图(顺序图)sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html) - [面向对象编程三大特性 ------ 封装、继承、多态](http://blog.csdn.net/jianyuerensheng/article/details/51602015) + From 99a1aeb51d11c22ee2221d201e584cb7955b4138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Fri, 17 Aug 2018 21:36:50 +0800 Subject: [PATCH 003/136] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f35ee455..942d6096 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ ## 算法 :pencil2: +- [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) + + 排序、并查集、栈和队列、红黑树、散列表。 + - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) 目录根据原书第二版进行编排,代码和原书有所不同,尽量比原书更简洁。 @@ -21,10 +25,6 @@ 对题目做了一个大致分类,并对每种题型的解题思路做了总结。 -- [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) - - 排序、并查集、栈和队列、红黑树、散列表。 - ## 操作系统 :computer: - [计算机操作系统](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机操作系统.md) From d33f9a31119bf9703f78d144a97b2533f80995e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Sat, 18 Aug 2018 16:29:59 +0800 Subject: [PATCH 004/136] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 942d6096..3209d82f 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,6 @@ ## 算法 :pencil2: -- [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) - - 排序、并查集、栈和队列、红黑树、散列表。 - - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) 目录根据原书第二版进行编排,代码和原书有所不同,尽量比原书更简洁。 @@ -24,6 +20,10 @@ - [Leetcode 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Leetcode%20题解.md) 对题目做了一个大致分类,并对每种题型的解题思路做了总结。 + + - [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) + + 排序、并查集、栈和队列、红黑树、散列表。 ## 操作系统 :computer: From f100a61a61dea9f7c09ee9493fd0fc8be89568bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Sat, 18 Aug 2018 16:30:19 +0800 Subject: [PATCH 005/136] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3209d82f..f9c604d9 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ 对题目做了一个大致分类,并对每种题型的解题思路做了总结。 - - [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) + - [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) 排序、并查集、栈和队列、红黑树、散列表。 From fad52dbef4167ace6a352e7c9dd9bf57f52ceb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Sat, 18 Aug 2018 16:30:33 +0800 Subject: [PATCH 006/136] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9c604d9..ce7257e5 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ - [算法](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/算法.md) - 排序、并查集、栈和队列、红黑树、散列表。 + 排序、并查集、栈和队列、红黑树、散列表。 ## 操作系统 :computer: From 7186c28cc5a3c42d228188c579f2d7161b4634ac Mon Sep 17 00:00:00 2001 From: zhang xuelong <35026038+zhangxuelong10@users.noreply.github.com> Date: Sun, 19 Aug 2018 18:33:49 +0800 Subject: [PATCH 007/136] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8B=BC=E5=86=99?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 基础.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index b329e0bc..44ca873a 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -707,7 +707,7 @@ public class EqualExample { ## hashCode() -hasCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。 +hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。 在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。 From d10ec622b02fff0a465ad8e93ce21a32df3dfe2e Mon Sep 17 00:00:00 2001 From: RocXing <120695313@qq.com> Date: Mon, 20 Aug 2018 18:46:03 +0800 Subject: [PATCH 008/136] =?UTF-8?q?=E8=A1=A5=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 并发.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 64f9e7d6..ea8b2898 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -185,7 +185,7 @@ public static void main(String[] args) { } ``` ## 三种实现方式的比较 -- 实现Runnable接又可以避免Java单继承特性而带来的局限;增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。 +- 实现Runnable接口又可以避免Java单继承特性而带来的局限;增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。 - 继承Thread类和实现Runnable方法启动线 程都是使用start方法,然后JVM虚拟机将此线程放到就绪队列中,如果有处理机可用, 则执行run方法。 - 实现Callable接又要实现call方法,并且线 程执行完毕后会有返回值。其他的两种都是 重写run方法,没有返回值。 ## 实现接口 VS 继承 Thread From 67322b7a32ddf156827a0977a17493e3a3000509 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 20 Aug 2018 20:32:42 +0800 Subject: [PATCH 009/136] auto commit --- notes/Docker.md | 11 ++++++----- notes/Java 并发.md | 5 +---- notes/Leetcode 题解.md | 9 ++++----- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/notes/Docker.md b/notes/Docker.md index f230f762..80108896 100644 --- a/notes/Docker.md +++ b/notes/Docker.md @@ -30,15 +30,15 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程 ## 启动速度 -启动虚拟机需要启动虚拟机的操作系统,再启动相应的应用,这个过程会非常慢; +启动虚拟机需要启动虚拟机的操作系统,再启动应用,这个过程非常慢; 而启动 Docker 相当于启动宿主操作系统上的一个进程。 ## 占用资源 -虚拟机是一个完整的操作系统,需要占用大量的磁盘空间、内存和 CPU,一台机器只能开启几十个的虚拟机。 +虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU,一台机器只能开启几十个的虚拟机。 -而 Docker 只是一个进程,只需要将应用以及相应的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 +而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 参考资料: @@ -58,7 +58,7 @@ Docker 使用分层技术和镜像,使得应用可以更容易复用重复部 ## 更容易扩展 -可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像得到我们想要的镜像非常容易。 +可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。 参考资料: @@ -91,7 +91,7 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服 镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。 -在构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。 +构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。

@@ -100,3 +100,4 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服 - [How to Create Docker Container using Dockerfile](https://linoxide.com/linux-how-to/dockerfile-create-docker-container/) - [理解 Docker(2):Docker 镜像](http://www.cnblogs.com/sammyliu/p/5877964.html) + diff --git a/notes/Java 并发.md b/notes/Java 并发.md index ea8b2898..d3682d33 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -184,10 +184,7 @@ public static void main(String[] args) { mt.start(); } ``` -## 三种实现方式的比较 -- 实现Runnable接口又可以避免Java单继承特性而带来的局限;增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。 -- 继承Thread类和实现Runnable方法启动线 程都是使用start方法,然后JVM虚拟机将此线程放到就绪队列中,如果有处理机可用, 则执行run方法。 -- 实现Callable接又要实现call方法,并且线 程执行完毕后会有返回值。其他的两种都是 重写run方法,没有返回值。 + ## 实现接口 VS 继承 Thread 实现接口会更好一些,因为: diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 68af3cb7..04a751c7 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -3602,7 +3602,7 @@ public int countPrimes(int n) { ```java int gcd(int a, int b) { - return b == 0 ? a : gcd(b, a% b); + return b == 0 ? a : gcd(b, a % b); } ``` @@ -3673,7 +3673,7 @@ public String convertToBase7(int num) { } ``` -Java 中 static String toString(int num, int radix) 可以将一个整数转换为 redix 进制表示的字符串。 +Java 中 static String toString(int num, int radix) 可以将一个整数转换为 radix 进制表示的字符串。 ```java public String convertToBase7(int num) { @@ -6403,7 +6403,6 @@ public int maxChunksToSorted(int[] arr) { } ``` - ## 图 ### 二分图 @@ -6620,6 +6619,7 @@ public int[] findRedundantConnection(int[][] edges) { } private class UF { + private int[] id; UF(int N) { @@ -6665,7 +6665,7 @@ x ^ x = 0 x & x = x x | x = x ``` - 利用 x ^ 1s = \~x 的特点,可以将位级表示翻转;利用 x ^ x = 0 的特点,可以将三个数中重复的两个数去除,只留下另一个数。 -- 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask :00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。 +- 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask:00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。 - 利用 x | 0s = x 和 x | 1s = 1s 的特点,可以实现设值操作。一个数 num 与 mask:00111100 进行位或操作,将 num 中与 mask 的 1 部分相对应的位都设置为 1。 位与运算技巧: @@ -6910,7 +6910,6 @@ public boolean isPowerOfFour(int num) { } ``` - **判断一个数的位级表示是否不会出现连续的 0 和 1** [693. Binary Number with Alternating Bits (Easy)](https://leetcode.com/problems/binary-number-with-alternating-bits/description/) From f7f68ba1f86b7af5d938dbad8630f7dbfae124a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Mon, 20 Aug 2018 20:50:41 +0800 Subject: [PATCH 010/136] Update README.md --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index ce7257e5..bf186a04 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ -## 算法 :pencil2: +### 算法 :pencil2: - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) @@ -25,7 +25,7 @@ 排序、并查集、栈和队列、红黑树、散列表。 -## 操作系统 :computer: +### 操作系统 :computer: - [计算机操作系统](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机操作系统.md) @@ -35,7 +35,7 @@ 基本实现原理以及基本操作。 -## 网络 :cloud: +### 网络 :cloud: - [计算机网络](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机网络.md) @@ -49,7 +49,7 @@ I/O 模型、I/O 多路复用。 -## 面向对象 :couple: +### 面向对象 :couple: - [设计模式](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/设计模式.md) @@ -59,7 +59,7 @@ 三大原则(继承、封装、多态)、类图、设计原则。 -## 数据库 :floppy_disk: +### 数据库 :floppy_disk: - [数据库系统原理](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/数据库系统原理.md) @@ -81,7 +81,7 @@ 五种数据类型、字典和跳跃表数据结构、使用场景、和 Memcache 的比较、淘汰策略、持久化、文件事件的 Reactor 模式、复制。 -## Java :coffee: +### Java :coffee: - [Java 基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Java%20基础.md) @@ -103,7 +103,7 @@ NIO 的原理以及实例。 -## 系统设计 :bulb: +### 系统设计 :bulb: - [系统设计基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/系统设计基础.md) @@ -129,7 +129,7 @@ 消息处理模型、使用场景、可靠性 -## 工具 :hammer: +### 工具 :hammer: - [Git](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Git.md) @@ -147,7 +147,7 @@ 构建工具的基本概念、主流构建工具介绍。 -## 编码实践 :speak_no_evil: +### 编码实践 :speak_no_evil: - [重构](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/重构.md) @@ -161,9 +161,9 @@ Google 开源项目的代码风格规范。 -## 后记 :memo: +### 后记 :memo: -### About +#### About 这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。 @@ -171,7 +171,7 @@ [BOOKLIST](https://github.com/CyC2018/Interview-Notebook/blob/master/BOOKLIST.md),这个书单是笔者至今看的一些比较好的技术书籍,虽然没有全都看完,但每本书多多少少都看了一部分。 -### How To Contribute +#### How To Contribute 笔记内容是笔者一个字一个字打上去的,难免会有一些笔误,如果发现笔误可直接在相应文档进行编辑修改。 @@ -179,7 +179,7 @@ 欢迎在 Issue 中提交对本仓库的改进建议~ -### Typesetting +#### Typesetting 笔记内容按照 [中文文案排版指北](http://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版,以保证内容的可读性。 @@ -187,7 +187,7 @@ 笔者将自己实现的文档排版功能提取出来,放在 Github Page 中,无需下载安装即可免费使用:[Text-Typesetting](https://github.com/CyC2018/Markdown-Typesetting)。 -### Uploading +#### Uploading 笔者在本地使用为知笔记软件进行书写,为了方便将本地笔记内容上传到 Github 上,实现了一整套自动化上传方案,包括文本文件的导出、提取图片、Markdown 文档转换、Git 同步。 @@ -195,21 +195,21 @@ 笔者将自己实现文档转换功能提取出来,方便大家在需要将本地 Markdown 上传到 Github,或者制作项目 README 文档时生成目录时使用:[GFM-Converter](https://github.com/CyC2018/GFM-Converter)。 -### License +#### License 在对本作品进行演绎时,请署名并以相同方式共享。 知识共享许可协议 -### Statement +#### Statement 本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) -### Logo +#### Logo Power by [logomakr](https://logomakr.com/). -### Acknowledgements +#### Acknowledgements 感谢以下人员对本仓库做出的贡献,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与笔者联系。 From 13e069030293de666b6c99fd928dfdaeb51f505e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Mon, 20 Aug 2018 20:58:21 +0800 Subject: [PATCH 011/136] Update README.md --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bf186a04..3e829c1b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ | Ⅰ | Ⅱ | Ⅲ | Ⅳ | Ⅴ | Ⅵ | Ⅶ | Ⅷ | Ⅸ | Ⅹ | | :--------: | :---------: | :---------: | :---------: | :---------: | :---------:| :---------: | :-------: | :-------:| :------:| -| 算法[:pencil2:](#算法-pencil2) | 操作系统[:computer:](#操作系统-computer)|网络[:cloud:](#网络-cloud) | 面向对象[:couple:](#面向对象-couple) |数据库[:floppy_disk:](#数据库-floppy_disk)| Java [:coffee:](#java-coffee)| 系统设计[:bulb:](#系统设计-bulb)| 工具[:hammer:](#工具-hammer)| 编码实践[:speak_no_evil:](#编码实践-speak_no_evil)| 后记[:memo:](#后记-memo) | +| 算法[:pencil2:](#pencil2-算法) | 操作系统[:computer:](#computer-操作系统)|网络[:cloud:](#cloud-网络) | 面向对象[:couple:](#couple-面向对象) |数据库[:floppy_disk:](#floppy_disk-数据库)| Java [:coffee:](#coffee-java)| 系统设计[:bulb:](#bulb-系统设计)| 工具[:hammer:](#hammer-工具)| 编码实践[:speak_no_evil:](#speak_no_evil-编码实践)| 后记[:memo:](#memo-后记) |
@@ -11,7 +11,7 @@ -### 算法 :pencil2: +## :pencil2: 算法 - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) @@ -25,7 +25,7 @@ 排序、并查集、栈和队列、红黑树、散列表。 -### 操作系统 :computer: +## :computer: 操作系统 - [计算机操作系统](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机操作系统.md) @@ -35,7 +35,7 @@ 基本实现原理以及基本操作。 -### 网络 :cloud: +## :cloud: 网络 - [计算机网络](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机网络.md) @@ -49,7 +49,7 @@ I/O 模型、I/O 多路复用。 -### 面向对象 :couple: +## :couple: 面向对象 - [设计模式](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/设计模式.md) @@ -59,7 +59,7 @@ 三大原则(继承、封装、多态)、类图、设计原则。 -### 数据库 :floppy_disk: +## :floppy_disk: 数据库 - [数据库系统原理](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/数据库系统原理.md) @@ -81,7 +81,7 @@ 五种数据类型、字典和跳跃表数据结构、使用场景、和 Memcache 的比较、淘汰策略、持久化、文件事件的 Reactor 模式、复制。 -### Java :coffee: +## :coffee: Java - [Java 基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Java%20基础.md) @@ -103,7 +103,7 @@ NIO 的原理以及实例。 -### 系统设计 :bulb: +## :bulb: 系统设计 - [系统设计基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/系统设计基础.md) @@ -129,7 +129,7 @@ 消息处理模型、使用场景、可靠性 -### 工具 :hammer: +## :hammer: 工具 - [Git](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Git.md) @@ -147,7 +147,7 @@ 构建工具的基本概念、主流构建工具介绍。 -### 编码实践 :speak_no_evil: +## :speak_no_evil: 编码实践 - [重构](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/重构.md) @@ -161,9 +161,9 @@ Google 开源项目的代码风格规范。 -### 后记 :memo: +## :memo: 后记 -#### About +### About 这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。 @@ -171,7 +171,7 @@ [BOOKLIST](https://github.com/CyC2018/Interview-Notebook/blob/master/BOOKLIST.md),这个书单是笔者至今看的一些比较好的技术书籍,虽然没有全都看完,但每本书多多少少都看了一部分。 -#### How To Contribute +### How To Contribute 笔记内容是笔者一个字一个字打上去的,难免会有一些笔误,如果发现笔误可直接在相应文档进行编辑修改。 @@ -179,7 +179,7 @@ 欢迎在 Issue 中提交对本仓库的改进建议~ -#### Typesetting +### Typesetting 笔记内容按照 [中文文案排版指北](http://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版,以保证内容的可读性。 @@ -187,7 +187,7 @@ 笔者将自己实现的文档排版功能提取出来,放在 Github Page 中,无需下载安装即可免费使用:[Text-Typesetting](https://github.com/CyC2018/Markdown-Typesetting)。 -#### Uploading +### Uploading 笔者在本地使用为知笔记软件进行书写,为了方便将本地笔记内容上传到 Github 上,实现了一整套自动化上传方案,包括文本文件的导出、提取图片、Markdown 文档转换、Git 同步。 @@ -195,21 +195,21 @@ 笔者将自己实现文档转换功能提取出来,方便大家在需要将本地 Markdown 上传到 Github,或者制作项目 README 文档时生成目录时使用:[GFM-Converter](https://github.com/CyC2018/GFM-Converter)。 -#### License +### License 在对本作品进行演绎时,请署名并以相同方式共享。 知识共享许可协议 -#### Statement +### Statement 本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) -#### Logo +### Logo Power by [logomakr](https://logomakr.com/). -#### Acknowledgements +### Acknowledgements 感谢以下人员对本仓库做出的贡献,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与笔者联系。 From ded6dee5cd049d22fc558b8e5e755c33c0b71b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Mon, 20 Aug 2018 20:59:44 +0800 Subject: [PATCH 012/136] Update README.md --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3e829c1b..d511fa7c 100644 --- a/README.md +++ b/README.md @@ -195,12 +195,6 @@ 笔者将自己实现文档转换功能提取出来,方便大家在需要将本地 Markdown 上传到 Github,或者制作项目 README 文档时生成目录时使用:[GFM-Converter](https://github.com/CyC2018/GFM-Converter)。 -### License - -在对本作品进行演绎时,请署名并以相同方式共享。 - -知识共享许可协议 - ### Statement 本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) @@ -235,5 +229,9 @@ Power by [logomakr](https://logomakr.com/). +### License +在对本作品进行演绎时,请署名并以相同方式共享。 + +知识共享许可协议 From db08ad2cda7d49e8d93e34c9b6397380cf27bae0 Mon Sep 17 00:00:00 2001 From: Elong Date: Tue, 21 Aug 2018 15:11:03 +0800 Subject: [PATCH 013/136] =?UTF-8?q?Update=20Java=20=E5=B9=B6=E5=8F=91.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文字描述修改的更加严谨一些 --- notes/Java 并发.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 并发.md b/notes/Java 并发.md index d3682d33..16e20a24 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -1020,7 +1020,7 @@ ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率。每个线 如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。 -以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值为 997 而不是 1000。 +以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值一般情况下小于 1000。 ```java public class ThreadUnsafeExample { From cd354fb46cd472b9b20a206df89ae7b83bb0b890 Mon Sep 17 00:00:00 2001 From: wangxujian-laixuzhui <33362969+wangxujian-laixuzhui@users.noreply.github.com> Date: Tue, 21 Aug 2018 18:29:57 +0800 Subject: [PATCH 014/136] =?UTF-8?q?=E5=BF=AB=E6=8E=92=E4=B8=8D=E7=A8=B3?= =?UTF-8?q?=E5=AE=9A=EF=BC=8C=E5=A6=82221=EF=BC=8C=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E4=B8=AA2=E4=BC=9A=E5=92=8C1=E4=BA=A4=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/算法.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/算法.md b/notes/算法.md index 30467b42..8007375b 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -770,7 +770,7 @@ public class HeapSort> extends Sort { | 算法 | 稳定 | 时间复杂度 | 空间复杂度 | 备注 | | :---: | :---: |:---: | :---: | :---: | -| 选择排序 | √| N2 | 1 | | +| 选择排序 | ×| N2 | 1 | | | 冒泡排序 | √ | N2 | 1 | | | 插入排序 | √ | N \~ N2 | 1 | 时间复杂度和初始顺序有关 | | 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | | From d4610276542bc6ebd4940a0f0845cc27ce4b74ea Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 21 Aug 2018 20:05:55 +0800 Subject: [PATCH 015/136] auto commit --- notes/Java 并发.md | 2 +- notes/攻击技术.md | 2 +- notes/消息队列.md | 13 +++++++------ notes/算法.md | 2 +- notes/缓存.md | 30 +++++++++--------------------- 5 files changed, 19 insertions(+), 30 deletions(-) diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 16e20a24..1403f764 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -1020,7 +1020,7 @@ ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率。每个线 如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。 -以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值一般情况下小于 1000。 +以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值有可能小于 1000。 ```java public class ThreadUnsafeExample { diff --git a/notes/攻击技术.md b/notes/攻击技术.md index d5a735ba..46dd4616 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -207,7 +207,7 @@ ResultSet rs = stmt.executeQuery(); 拒绝服务攻击(denial-of-service attack,DoS),亦称洪水攻击,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。 -分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用网络上两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。 +分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。 # 参考资料 diff --git a/notes/消息队列.md b/notes/消息队列.md index c5687e8a..209d962a 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -9,6 +9,7 @@ * [三、可靠性](#三可靠性) * [发送端的可靠性](#发送端的可靠性) * [接收端的可靠性](#接收端的可靠性) +* [参考资料](#参考资料) @@ -29,15 +30,10 @@ 发布与订阅模式和观察者模式有以下不同: - 观察者模式中,观察者和主题都知道对方的存在;而在发布与订阅模式中,发布者与订阅者不知道对方的存在,它们之间通过频道进行通信。 -- 观察者模式是同步的,当事件触发时,主题会去调用观察者的方法,然后等待方法返回;而发布与订阅模式是异步的,发布者向频道发送一个消息之后,就不需要关心订阅者何时去订阅这个消息。 +- 观察者模式是同步的,当事件触发时,主题会调用观察者的方法,然后等待方法返回;而发布与订阅模式是异步的,发布者向频道发送一个消息之后,就不需要关心订阅者何时去订阅这个消息,可以立即返回。

-参考: - -- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/) -- [消息队列中点对点与发布订阅区别](https://blog.csdn.net/lizhitao/article/details/47723105) - # 二、使用场景 ## 异步处理 @@ -78,3 +74,8 @@ - 保证接收端处理消息的业务逻辑具有幂等性:只要具有幂等性,那么消费多少次消息,最后处理的结果都是一样的。 - 保证消息具有唯一编号,并使用一张日志表来记录已经消费的消息编号。 + +# 参考资料 + +- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/) +- [消息队列中点对点与发布订阅区别](https://blog.csdn.net/lizhitao/article/details/47723105) diff --git a/notes/算法.md b/notes/算法.md index 8007375b..152adfda 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -770,7 +770,7 @@ public class HeapSort> extends Sort { | 算法 | 稳定 | 时间复杂度 | 空间复杂度 | 备注 | | :---: | :---: |:---: | :---: | :---: | -| 选择排序 | ×| N2 | 1 | | +| 选择排序 | × | N2 | 1 | | | 冒泡排序 | √ | N2 | 1 | | | 插入排序 | √ | N \~ N2 | 1 | 时间复杂度和初始顺序有关 | | 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | | diff --git a/notes/缓存.md b/notes/缓存.md index 9a9f2810..ed834253 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -6,6 +6,7 @@ * [五、缓存问题](#五缓存问题) * [六、数据分布](#六数据分布) * [七、一致性哈希](#七一致性哈希) +* [参考资料](#参考资料) @@ -29,10 +30,6 @@ - LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最远的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 -参考资料: - -- [缓存那些事](https://tech.meituan.com/cache_about.html) - # 二、LRU 以下是一个基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: @@ -143,10 +140,6 @@ public class LRU implements Iterable { } ``` -源代码: - -- [CyC2018/Algorithm](https://github.com/CyC2018/Algorithm/tree/master/Caching) - # 三、缓存位置 ## 浏览器 @@ -169,7 +162,7 @@ public class LRU implements Iterable { 使用 Redis、Memcache 等分布式缓存将数据缓存在分布式缓存系统中。 -相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存。而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 +相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 ## 数据库缓存 @@ -177,7 +170,7 @@ MySQL 等数据库管理系统具有自己的查询缓存机制来提高 SQL 查 # 四、CDN -内容分发网络(Content distribution network,CDN)是一种通过互连的网络系统,利用更靠近用户的服务器更快更可靠地将 HTML、CSS、JavaScript、音乐、图片、视频等静态资源分发给用户。 +内容分发网络(Content distribution network,CDN)是一种互连的网络系统,它利用更靠近用户的服务器从而更快更可靠地将 HTML、CSS、JavaScript、音乐、图片、视频等静态资源分发给用户。 CDN 主要有以下优点: @@ -187,11 +180,6 @@ CDN 主要有以下优点:

-参考资料: - -- [内容分发网络](https://zh.wikipedia.org/wiki/%E5%85%A7%E5%AE%B9%E5%82%B3%E9%81%9E%E7%B6%B2%E8%B7%AF) -- [How Aspiration CDN helps to improve your website loading speed?](https://www.aspirationhosting.com/aspiration-cdn/) - # 五、缓存问题 ## 缓存穿透 @@ -213,7 +201,7 @@ CDN 主要有以下优点: - 为了防止缓存在同一时间大面积过期导致的缓存雪崩,可以通过观察用户行为,合理设置缓存过期时间来实现; - 为了防止缓存服务器宕机出现的缓存雪崩,可以使用分布式缓存,分布式缓存中每一个节点只缓存部分的数据,当某个节点宕机时可以保证其它节点的缓存仍然可用。 -- 也可以在进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 +- 也可以进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 ## 缓存一致性 @@ -243,10 +231,6 @@ CDN 主要有以下优点: - 能保持数据原有的顺序; - 并且能够准确控制每台服务器存储的数据量,从而使得存储空间的利用率最大。 -参考资料: - -- 大规模分布式存储系统 - # 七、一致性哈希 Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据失效的问题。 @@ -267,6 +251,10 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了 数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得大,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 -参考资料: +# 参考资料 +- 大规模分布式存储系统 +- [缓存那些事](https://tech.meituan.com/cache_about.html) - [一致性哈希算法](https://my.oschina.net/jayhu/blog/732849) +- [内容分发网络](https://zh.wikipedia.org/wiki/%E5%85%A7%E5%AE%B9%E5%82%B3%E9%81%9E%E7%B6%B2%E8%B7%AF) +- [How Aspiration CDN helps to improve your website loading speed?](https://www.aspirationhosting.com/aspiration-cdn/) From 25cd99a8d03637bbc624e58e3991a41c36810c1a Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 21 Aug 2018 20:14:05 +0800 Subject: [PATCH 016/136] auto commit --- notes/算法.md | 2 +- pics/766aedd0-1b00-4065-aa2b-7d31138df84f.png | Bin 0 -> 19456 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 pics/766aedd0-1b00-4065-aa2b-7d31138df84f.png diff --git a/notes/算法.md b/notes/算法.md index 152adfda..25d1550e 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -507,7 +507,7 @@ public class QuickSort> extends Sort { 取 a[l] 作为切分元素,然后从数组的左端向右扫描直到找到第一个大于等于它的元素,再从数组的右端向左扫描找到第一个小于等于它的元素,交换这两个元素。不断进行这个过程,就可以保证左指针 i 的左侧元素都不大于切分元素,右指针 j 的右侧元素都不小于切分元素。当两个指针相遇时,将切分元素 a[l] 和 a[j] 交换位置。 -

+

```java private int partition(T[] nums, int l, int h) { diff --git a/pics/766aedd0-1b00-4065-aa2b-7d31138df84f.png b/pics/766aedd0-1b00-4065-aa2b-7d31138df84f.png new file mode 100644 index 0000000000000000000000000000000000000000..e8a69bff4827a53c56bc89507c42318a2aa8a0d2 GIT binary patch literal 19456 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 literal 0 HcmV?d00001 From 673c9aa04a4ea67badff80df67cdd8aa3d8ad2df Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 21 Aug 2018 20:44:53 +0800 Subject: [PATCH 017/136] auto commit --- notes/分布式.md | 105 ++++++++++++++++++------------------------ notes/系统设计基础.md | 8 ++-- 2 files changed, 48 insertions(+), 65 deletions(-) diff --git a/notes/分布式.md b/notes/分布式.md index c048b43e..e98f2860 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -19,10 +19,11 @@ * [五、Paxos](#五paxos) * [执行过程](#执行过程) * [约束条件](#约束条件) -* [五、Raft](#五raft) +* [六、Raft](#六raft) * [单个 Candidate 的竞选](#单个-candidate-的竞选) * [多个 Candidate 竞选](#多个-candidate-竞选) - * [日志复制](#日志复制) + * [数据同步](#数据同步) +* [参考](#参考) @@ -35,7 +36,7 @@ - 互斥量为 1 表示有其它进程在使用锁,此时处于锁定状态; - 互斥量为 0 表示未锁定状态。 -1 和 0 可以用一个整型值表示,也可以用某个数据存在或者不存在表示,存在表示互斥量为 1。 +1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示,存在表示互斥量为 1。 ## 数据库的唯一索引 @@ -43,7 +44,7 @@ 存在以下几个问题: -- 锁没有失效时间,解锁失败的话其它进程无法再获得锁。 +- 锁没有失效时间,解锁失败的话其它进程无法再获得该锁。 - 只能是非阻塞锁,插入失败直接就报错了,无法重试。 - 不可重入,已经获得锁的进程也必须重新获取锁。 @@ -59,7 +60,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时仍然可用。 -- 尝试从 N 个相互独立 Redis 实例获取锁,如果一个实例不可用,应该尽快尝试下一个; +- 尝试从 N 个相互独立 Redis 实例获取锁; - 计算获取锁消耗的时间,只有当这个时间小于锁的过期时间,并且从大多数(N / 2 + 1)实例上获取了锁,那么就认为锁获取成功了; - 如果锁获取失败,就到每个实例上释放锁。 @@ -67,7 +68,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 ### 1. Zookeeper 抽象模型 -Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示它的父节点为 /app1。 +Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父节点为 /app1。

@@ -96,21 +97,15 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 -参考: - -- [Distributed locks with Redis](https://redis.io/topics/distlock) -- [浅谈分布式锁](http://www.linkedkeeper.com/detail/blog.action?bid=1023) -- [基于 Zookeeper 的分布式锁](http://www.dengshenyu.com/java/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/10/23/zookeeper-distributed-lock.html) - # 二、分布式事务 -指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。 +指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。 + +例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。 ## 本地消息表 -### 1. 原理 - -本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性。 +本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。 1. 在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。 2. 之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。 @@ -118,23 +113,19 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示

-### 2. 分析 - -本地消息表利用了本地事务来实现分布式事务,并且使用了消息队列来保证最终一致性。 - ## 2PC 两阶段提交(Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。 ### 1. 运行过程 -(一)准备阶段 +#### 1.1 准备阶段 协调者询问参与者事务是否执行成功,参与者发回事务执行结果。

-(二)提交阶段 +#### 1.2 提交阶段 如果事务在每个参与者上都执行成功,事务协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。 @@ -144,28 +135,22 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 ### 2. 存在的问题 -(一)同步阻塞 +#### 2.1 同步阻塞 所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作。 -(二)单点问题 +#### 2.2 单点问题 协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其它操作。 -(三)数据不一致 +#### 2.3 数据不一致 在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。 -(四)太过保守 +#### 2.4 太过保守 任意一个节点失败就会导致整个事务失败,没有完善的容错机制。 -参考: - -- [聊聊分布式事务,再说说解决方案](https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html) -- [分布式系统的事务处理](https://coolshell.cn/articles/10910.html) -- [深入理解分布式事务](https://juejin.im/entry/577c6f220a2b5800573492be) - # 三、CAP 分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。 @@ -184,7 +169,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 ## 分区容忍性 @@ -198,16 +183,11 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 可用性和一致性往往是冲突的,很难都使它们同时满足。在多个节点之间进行数据同步时, -* 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; -* 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。 +- 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; +- 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。

-参考: - -- 倪超. 从 Paxos 到 ZooKeeper : 分布式一致性原理与实践 [M]. 电子工业出版社, 2015. -- [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) - # 四、BASE BASE 是基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)三个短语的缩写。 @@ -292,66 +272,69 @@ Acceptor 接收到接受请求时,如果序号大于等于该 Acceptor 承诺 Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性。 -参考: +# 六、Raft -- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) -- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) - -# 五、Raft - -Raft 和 Paxos 类似,但是更容易理解,也更容易实现。 - -Raft 主要是用来竞选主节点。 +Raft 也是分布式一致性协议,主要是用来竞选主节点。 ## 单个 Candidate 的竞选 有三种节点:Follower、Candidate 和 Leader。Leader 会周期性的发送心跳包给 Follower。每个 Follower 都设置了一个随机的竞选超时时间,一般为 150ms\~300ms,如果在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段。 -* 下图表示一个分布式系统的最初阶段,此时只有 Follower,没有 Leader。Follower A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。 +- 下图展示一个分布式系统的最初阶段,此时只有 Follower 没有 Leader。Node A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。

-* 此时 A 发送投票请求给其它所有节点。 +- 此时 Node A 发送投票请求给其它所有节点。

-* 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。 +- 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。

-* 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。 +- 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。

## 多个 Candidate 竞选 -* 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票,例如下图中 Candidate B 和 Candidate D 都获得两票,因此需要重新开始投票。 +- 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票。例如下图中 Node B 和 Node D 都获得两票,需要重新开始投票。

-* 当重新开始投票时,由于每个节点设置的随机竞选超时时间不同,因此能下一次再次出现多个 Candidate 并获得同样票数的概率很低。 +- 由于每个节点设置的随机竞选超时时间不同,因此下一次再次出现多个 Candidate 并获得同样票数的概率很低。

-## 日志复制 +## 数据同步 -* 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。 +- 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。

-* Leader 会把修改复制到所有 Follower。 +- Leader 会把修改复制到所有 Follower。

-* Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。 +- Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。

-* 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。 +- 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。

-参考: +# 参考 +- 倪超. 从 Paxos 到 ZooKeeper : 分布式一致性原理与实践 [M]. 电子工业出版社, 2015. +- [Distributed locks with Redis](https://redis.io/topics/distlock) +- [浅谈分布式锁](http://www.linkedkeeper.com/detail/blog.action?bid=1023) +- [基于 Zookeeper 的分布式锁](http://www.dengshenyu.com/java/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/10/23/zookeeper-distributed-lock.html) - [Raft: Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft) +- [聊聊分布式事务,再说说解决方案](https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html) +- [分布式系统的事务处理](https://coolshell.cn/articles/10910.html) +- [深入理解分布式事务](https://juejin.im/entry/577c6f220a2b5800573492be) +- [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) +- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) +- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index 805764a9..b6a3ddf5 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -68,7 +68,7 @@ 应用服务器只要不具有状态,那么就可以很容易地通过负载均衡器向集群中添加新的服务器。 -关系型数据库的伸缩性通过 Sharding 来实现,将数据按一定的规则分布到不同的节点上,从而解决单台存储服务器存储空间限制。 +关系型数据库的伸缩性通过 Sharding 来实现,将数据按一定的规则分布到不同的节点上,从而解决单台存储服务器的存储空间限制。 对于非关系型数据库,它们天生就是为海量数据而诞生,对伸缩性的支持特别好。 @@ -78,7 +78,7 @@ 实现可扩展主要有两种方式: -- 使用消息队列进行解耦,应用之间通过消息传递的方式进行通信; +- 使用消息队列进行解耦,应用之间通过消息传递进行通信; - 使用分布式服务将业务和可复用的服务分离开来,业务使用分布式服务框架调用可复用的服务。新增的产品可以通过调用可复用的服务来实现业务逻辑,对其它产品没有影响。 # 四、可用性 @@ -87,7 +87,7 @@ 保证高可用的主要手段是使用冗余,当某个服务器故障时就请求其它服务器。 -应用服务器的冗余比较容易实现,只要保证应用服务器不具有状态,那么某个应用服务器故障时,负载均衡器将该应用服务器原先的用户请求转发到另一个应用服务器上不会对用户有任何影响。 +应用服务器的冗余比较容易实现,只要保证应用服务器不具有状态,那么某个应用服务器故障时,负载均衡器将该应用服务器原先的用户请求转发到另一个应用服务器上,不会对用户有任何影响。 存储服务器的冗余需要使用主从复制来实现,当主服务器故障时,需要提升从服务器为主服务器,这个过程称为切换。 @@ -97,7 +97,7 @@ ## 服务降级 -服务器降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。 +服务降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。 # 五、安全性 From 762c3c698c936492dbc03dec7bf821da4ad5364b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 23 Aug 2018 21:37:51 +0800 Subject: [PATCH 018/136] auto commit --- notes/Redis.md | 2 +- notes/剑指 offer 题解.md | 2 +- notes/构建工具.md | 2 +- notes/算法.md | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/notes/Redis.md b/notes/Redis.md index 8f231382..629fcdd8 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -549,7 +549,7 @@ def main(): # 十二、Sentinel -Sentinel(哨兵)可以监听主服务器,并在主服务器进入下线状态时,自动从从服务器中选举出新的主服务器。 +Sentinel(哨兵)可以监听集群中的服务器,并在主服务器进入下线状态时,自动从从服务器中选举出新的主服务器。 # 十三、分片 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 1bac6bbb..72c20173 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1082,7 +1082,7 @@ false ```java public boolean isNumeric(char[] str) { - if (str == null) + if (str == null || str.length == 0) return false; return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?"); } diff --git a/notes/构建工具.md b/notes/构建工具.md index c0e4acd5..ce157934 100644 --- a/notes/构建工具.md +++ b/notes/构建工具.md @@ -15,7 +15,7 @@ ## 运行单元测试 -不再需要在项目代码中添加测试代码,从而污染项目代码。 +不再需要在项目代码中添加测试代码,从而避免了污染项目代码。 ## 将源代码转化为可执行文件 diff --git a/notes/算法.md b/notes/算法.md index 25d1550e..a9f9e689 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -23,7 +23,7 @@ * [五、栈和队列](#五栈和队列) * [栈](#栈) * [队列](#队列) -* [六、查找](#六查找) +* [六、符号表](#六符号表) * [初级实现](#初级实现) * [二叉查找树](#二叉查找树) * [2-3 查找树](#2-3-查找树) @@ -1290,7 +1290,7 @@ public class ListQueue implements MyQueue { -# 六、查找 +# 六、符号表 符号表(Symbol Table)是一种存储键值对的数据结构,可以支持快速查找操作。 @@ -1411,9 +1411,9 @@ public class ListUnorderedST implements UnorderedST { 使用一对平行数组,一个存储键一个存储值。 -rank() 方法至关重要,当键在表中时,它能够知道该键的位置;当键不在表中时,它也能知道在何处插入新键。 +二分查找的 rank() 方法至关重要,当键在表中时,它能够知道该键的位置;当键不在表中时,它也能知道在何处插入新键。 -复杂度:二分查找最多需要 logN+1 次比较,使用二分查找实现的符号表的查找操作所需要的时间最多是对数级别的。但是插入操作需要移动数组元素,是线性级别的。 +二分查找最多需要 logN+1 次比较,使用二分查找实现的符号表的查找操作所需要的时间最多是对数级别的。但是插入操作需要移动数组元素,是线性级别的。 ```java public class BinarySearchOrderedST, Value> implements OrderedST { @@ -2254,7 +2254,7 @@ from H1 to H3 - c : 40 - d : 80 -可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码能让出现频率最高的字符的编码最短,从而保证整体的编码长度最短。 +可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码采用了贪心策略,使出现频率最高的字符的编码最短,从而保证整体的编码长度最短。 首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 From cf2e79d8329c53f7036594cf459be689ab45eb94 Mon Sep 17 00:00:00 2001 From: newbieof410 Date: Fri, 24 Aug 2018 10:35:57 +0800 Subject: [PATCH 019/136] Update MySQL.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改笔误 --- notes/MySQL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/MySQL.md b/notes/MySQL.md index 54067977..bb465ff3 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -214,7 +214,7 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai 一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。 ```sql -DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); +DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); ``` ```sql @@ -342,7 +342,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。 -当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓存单个数据库的压力。 +当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓解单个数据库的压力。

From 4f3fa83fc27e18a371b5940e937cdc34c0ef0bea Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 25 Aug 2018 23:12:21 +0800 Subject: [PATCH 020/136] auto commit --- notes/Docker.md | 11 +-- notes/Java 基础.md | 2 +- notes/Java 容器.md | 2 +- notes/Java 并发.md | 4 +- notes/Java 虚拟机.md | 2 +- notes/Leetcode 题解.md | 189 ++++++++++++++++++--------------------- notes/Linux.md | 26 +++--- notes/Redis.md | 2 +- notes/分布式.md | 105 +++++++++------------- notes/剑指 offer 题解.md | 14 ++- notes/攻击技术.md | 2 +- notes/构建工具.md | 2 +- notes/消息队列.md | 13 +-- notes/算法.md | 14 +-- notes/系统设计基础.md | 8 +- notes/缓存.md | 30 ++----- notes/设计模式.md | 76 ++++++++-------- notes/面向对象思想.md | 15 ++-- 18 files changed, 248 insertions(+), 269 deletions(-) diff --git a/notes/Docker.md b/notes/Docker.md index f230f762..80108896 100644 --- a/notes/Docker.md +++ b/notes/Docker.md @@ -30,15 +30,15 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程 ## 启动速度 -启动虚拟机需要启动虚拟机的操作系统,再启动相应的应用,这个过程会非常慢; +启动虚拟机需要启动虚拟机的操作系统,再启动应用,这个过程非常慢; 而启动 Docker 相当于启动宿主操作系统上的一个进程。 ## 占用资源 -虚拟机是一个完整的操作系统,需要占用大量的磁盘空间、内存和 CPU,一台机器只能开启几十个的虚拟机。 +虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 CPU,一台机器只能开启几十个的虚拟机。 -而 Docker 只是一个进程,只需要将应用以及相应的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 +而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 参考资料: @@ -58,7 +58,7 @@ Docker 使用分层技术和镜像,使得应用可以更容易复用重复部 ## 更容易扩展 -可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像得到我们想要的镜像非常容易。 +可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。 参考资料: @@ -91,7 +91,7 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服 镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。 -在构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。 +构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。

@@ -100,3 +100,4 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服 - [How to Create Docker Container using Dockerfile](https://linoxide.com/linux-how-to/dockerfile-create-docker-container/) - [理解 Docker(2):Docker 镜像](http://www.cnblogs.com/sammyliu/p/5877964.html) + diff --git a/notes/Java 基础.md b/notes/Java 基础.md index b329e0bc..44ca873a 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -707,7 +707,7 @@ public class EqualExample { ## hashCode() -hasCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。 +hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。 在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。 diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 9959e2ca..001f864c 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -742,7 +742,7 @@ new capacity : 00100000 对于一个 Key, -- 它的哈希值如果在第 6 位上为 0,那么取模得到的结果和之前一样; +- 它的哈希值如果在第 5 位上为 0,那么取模得到的结果和之前一样; - 如果为 1,那么得到的结果为原来的结果 +16。 ### 7. 扩容-计算数组容量 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 9cd5955b..1403f764 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -168,6 +168,8 @@ public static void main(String[] args) throws ExecutionException, InterruptedExc 同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。 +当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。 + ```java public class MyThread extends Thread { public void run() { @@ -1018,7 +1020,7 @@ ForkJoinPool 实现了工作窃取算法来提高 CPU 的利用率。每个线 如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。 -以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值为 997 而不是 1000。 +以下代码演示了 1000 个线程同时对 cnt 执行自增操作,操作结束之后它的值有可能小于 1000。 ```java public class ThreadUnsafeExample { diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index a4a4ba12..1bba557b 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -92,7 +92,7 @@ java -Xms1M -Xmx2M HackTheJava 对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现。 -JDK 1.7 之前,HotSpot 虚拟机把它当成永久代来进行垃圾回收。但是从 JDK 1.7 开始,已经把原本放在永久代的字符串常量池移到 Native Method 中。 +HotSpot 虚拟机把它当成永久代来进行垃圾回收。但是很难确定永久代的大小,因为它受到很多因素影响,并且每次 Full GC 之后永久代的大小都会改变,所以经常会抛出 OutOfMemoryError 异常。为了更容易管理方法区,从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。 ## 运行时常量池 diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 44f3d9dc..04a751c7 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2389,8 +2389,6 @@ private void backtracking(int row) {

-dp[N] 即为所求。 - 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 ```java @@ -2468,16 +2466,6 @@ private int rob(int[] nums, int first, int last) { } ``` -**母牛生产** - -[程序员代码面试指南-P181](#) - -题目描述:假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N,求 N 年后牛的数量。 - -第 i 年成熟的牛的数量为: - -

- **信件错排** 题目描述:有 N 个 信 和 信封,它们被打乱,求错误装信方式的数量。 @@ -2491,7 +2479,15 @@ private int rob(int[] nums, int first, int last) {

-dp[N] 即为所求。 +**母牛生产** + +[程序员代码面试指南-P181](#) + +题目描述:假设农场中成熟的母牛每年都会生 1 头小母牛,并且永远不会死。第一年有 1 只小母牛,从第二年开始,母牛开始生小母牛。每只小母牛 3 年之后成熟又可以生小母牛。给定整数 N,求 N 年后牛的数量。 + +第 i 年成熟的牛的数量为: + +

### 矩阵路径 @@ -2517,10 +2513,8 @@ public int minPathSum(int[][] grid) { int[] dp = new int[n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { - if (j == 0) { - dp[j] = dp[j]; // 只能从上侧走到该位置 - } else if (i == 0) { - dp[j] = dp[j - 1]; // 只能从左侧走到该位置 + if (i == 0) { + dp[j] = dp[j - 1]; } else { dp[j] = Math.min(dp[j - 1], dp[j]); } @@ -2584,17 +2578,18 @@ sumRange(0, 5) -> -3 ```java class NumArray { + private int[] sums; public NumArray(int[] nums) { - sums = new int[nums.length]; - for (int i = 0; i < nums.length; i++) { - sums[i] = i == 0 ? nums[0] : sums[i - 1] + nums[i]; + sums = new int[nums.length + 1]; + for (int i = 1; i <= nums.length; i++) { + sums[i] = sums[i - 1] + nums[i - 1]; } } public int sumRange(int i, int j) { - return i == 0 ? sums[j] : sums[j] - sums[i - 1]; + return sums[j + 1] - sums[i]; } } ``` @@ -2634,7 +2629,7 @@ return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] i dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。 -如果 A[i] - A[i - 1] == A[i - 1] - A[i - 2],表示 [A[i - 2], A[i - 1], A[i]] 是一个等差递增子区间。如果 [A[i - 3], A[i - 2], A[i - 1]] 是一个等差递增子区间,那么 [A[i - 3], A[i - 2], A[i - 1], A[i]] 也是。因此在这个条件下,dp[i] = dp[i-1] + 1。 +在 A[i] - A[i - 1] == A[i - 1] - A[i - 2] 的条件下,{A[i - 2], A[i - 1], A[i]} 是一个等差递增子区间。如果 {A[i - 3], A[i - 2], A[i - 1]} 是一个等差递增子区间,那么 {A[i - 3], A[i - 2], A[i - 1], A[i]} 也是等差递增子区间,dp[i] = dp[i-1] + 1。 ```java public int numberOfArithmeticSlices(int[] A) { @@ -2747,17 +2742,17 @@ public int numDecodings(String s) { ### 最长递增子序列 -已知一个序列 {S1, S2,...,Sn} ,取出若干数组成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个 **子序列** 。 +已知一个序列 {S1, S2,...,Sn},取出若干数组成新的序列 {Si1, Si2,..., Sim},其中 i1、i2 ... im 保持递增,即新序列中各个数仍然保持原数列中的先后顺序,称新序列为原序列的一个 **子序列** 。 如果在子序列中,当下标 ix > iy 时,Six > Siy,称子序列为原序列的一个 **递增子序列** 。 -定义一个数组 dp 存储最长递增子序列的长度,dp[n] 表示以 Sn 结尾的序列的最长递增子序列长度。对于一个递增子序列 {Si1, Si2,...,Sim},如果 im < n 并且 Sim < Sn ,此时 {Si1, Si2,..., Sim, Sn} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中,长度最长的那个递增子序列就是要找的,在长度最长的递增子序列上加上 Sn 就构成了以 Sn 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | Si < Sn && i < n} 。 +定义一个数组 dp 存储最长递增子序列的长度,dp[n] 表示以 Sn 结尾的序列的最长递增子序列长度。对于一个递增子序列 {Si1, Si2,...,Sim},如果 im < n 并且 Sim < Sn,此时 {Si1, Si2,..., Sim, Sn} 为一个递增子序列,递增子序列的长度增加 1。满足上述条件的递增子序列中,长度最长的那个递增子序列就是要找的,在长度最长的递增子序列上加上 Sn 就构成了以 Sn 为结尾的最长递增子序列。因此 dp[n] = max{ dp[i]+1 | Si < Sn && i < n} 。 因为在求 dp[n] 时可能无法找到一个满足条件的递增子序列,此时 {Sn} 就构成了递增子序列,需要对前面的求解方程做修改,令 dp[n] 最小为 1,即:

-对于一个长度为 N 的序列,最长递增子序列并不一定会以 SN 为结尾,因此 dp[N] 不是序列的最长递增子序列的长度,需要遍历 dp 数组找出最大值才是所要的结果,即 max{ dp[i] | 1 <= i <= N} 即为所求。 +对于一个长度为 N 的序列,最长递增子序列并不一定会以 SN 为结尾,因此 dp[N] 不是序列的最长递增子序列的长度,需要遍历 dp 数组找出最大值才是所要的结果,max{ dp[i] | 1 <= i <= N} 即为所求。 **最长递增子序列** @@ -2790,7 +2785,7 @@ for (int i = 0; i < n; i++) { return ret; ``` -以上解法的时间复杂度为 O(N2) ,可以使用二分查找将时间复杂度降低为 O(NlogN)。 +以上解法的时间复杂度为 O(N2),可以使用二分查找将时间复杂度降低为 O(NlogN)。 定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素。对于一个元素 x, @@ -2915,19 +2910,19 @@ public int wiggleMaxLength(int[] nums) { 定义一个二维数组 dp 用来存储最长公共子序列的长度,其中 dp[i][j] 表示 S1 的前 i 个字符与 S2 的前 j 个字符最长公共子序列的长度。考虑 S1i 与 S2j 值是否相等,分为两种情况: -- 当 S1i==S2j 时,那么就能在 S1 的前 i-1 个字符与 S2 的前 j-1 个字符最长公共子序列的基础上再加上 S1i 这个值,最长公共子序列长度加 1 ,即 dp[i][j] = dp[i-1][j-1] + 1。 -- 当 S1i != S2j 时,此时最长公共子序列为 S1 的前 i-1 个字符和 S2 的前 j 个字符最长公共子序列,与 S1 的前 i 个字符和 S2 的前 j-1 个字符最长公共子序列,它们的最大者,即 dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }。 +- 当 S1i==S2j 时,那么就能在 S1 的前 i-1 个字符与 S2 的前 j-1 个字符最长公共子序列的基础上再加上 S1i 这个值,最长公共子序列长度加 1,即 dp[i][j] = dp[i-1][j-1] + 1。 +- 当 S1i != S2j 时,此时最长公共子序列为 S1 的前 i-1 个字符和 S2 的前 j 个字符最长公共子序列,或者 S1 的前 i 个字符和 S2 的前 j-1 个字符最长公共子序列,取它们的最大者,即 dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }。 综上,最长公共子序列的状态转移方程为:

-对于长度为 N 的序列 S1 和 长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。 +对于长度为 N 的序列 S1 和长度为 M 的序列 S2,dp[N][M] 就是序列 S1 和序列 S2 的最长公共子序列长度。 与最长递增子序列相比,最长公共子序列有以下不同点: - 针对的是两个序列,求它们的最长公共子序列。 -- 在最长递增子序列中,dp[i] 表示以 Si 为结尾的最长递增子序列长度,子序列必须包含 Si ;在最长公共子序列中,dp[i][j] 表示 S1 中前 i 个字符与 S2 中前 j 个字符的最长公共子序列长度,不一定包含 S1i 和 S2j 。 +- 在最长递增子序列中,dp[i] 表示以 Si 为结尾的最长递增子序列长度,子序列必须包含 Si ;在最长公共子序列中,dp[i][j] 表示 S1 中前 i 个字符与 S2 中前 j 个字符的最长公共子序列长度,不一定包含 S1i 和 S2j。 - 在求最终解时,最长公共子序列中 dp[N][M] 就是最终解,而最长递增子序列中 dp[N] 不是最终解,因为以 SN 为结尾的最长递增子序列不一定是整个序列最长递增子序列,需要遍历一遍 dp 数组找到最大者。 ```java @@ -2956,9 +2951,7 @@ public int lengthOfLCS(int[] nums1, int[] nums2) { - 第 i 件物品没添加到背包,总体积不超过 j 的前 i 件物品的最大价值就是总体积不超过 j 的前 i-1 件物品的最大价值,dp[i][j] = dp[i-1][j]。 - 第 i 件物品添加到背包中,dp[i][j] = dp[i-1][j-w] + v。 -第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。 - -综上,0-1 背包的状态转移方程为: +第 i 件物品可添加也可以不添加,取决于哪种情况下最大价值更大。因此,0-1 背包的状态转移方程为:

@@ -2981,11 +2974,11 @@ public int knapsack(int W, int N, int[] weights, int[] values) { **空间优化** -在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道,前 i 件物品的状态仅由前 i-1 件物品的状态有关,因此可以将 dp 定义为一维数组,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时, +在程序实现时可以对 0-1 背包做优化。观察状态转移方程可以知道,前 i 件物品的状态仅与前 i-1 件物品的状态有关,因此可以将 dp 定义为一维数组,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此时,

-因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],以防止将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。 +因为 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],以防将 dp[i-1][j-w] 覆盖。也就是说要先计算 dp[i][j] 再计算 dp[i][j-w],在程序实现时需要按倒序来循环求解。 ```java public int knapsack(int W, int N, int[] weights, int[] values) { @@ -3205,7 +3198,7 @@ public int findMaxForm(String[] strs, int m, int n) { } ``` -**找零钱的方法数** +**找零钱的最少硬币数** [322. Coin Change (Medium)](https://leetcode.com/problems/coin-change/description/) @@ -3286,60 +3279,6 @@ public int combinationSum4(int[] nums, int target) { } ``` -**只能进行 k 次的股票交易** - -[188. Best Time to Buy and Sell Stock IV (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) - -```java -public int maxProfit(int k, int[] prices) { - int n = prices.length; - if (k >= n / 2) { // 这种情况下该问题退化为普通的股票交易问题 - int maxProfit = 0; - for (int i = 1; i < n; i++) { - if (prices[i] > prices[i - 1]) { - maxProfit += prices[i] - prices[i - 1]; - } - } - return maxProfit; - } - int[][] maxProfit = new int[k + 1][n]; - for (int i = 1; i <= k; i++) { - int localMax = maxProfit[i - 1][0] - prices[0]; - for (int j = 1; j < n; j++) { - maxProfit[i][j] = Math.max(maxProfit[i][j - 1], prices[j] + localMax); - localMax = Math.max(localMax, maxProfit[i - 1][j] - prices[j]); - } - } - return maxProfit[k][n - 1]; -} -``` - -**只能进行两次的股票交易** - -[123. Best Time to Buy and Sell Stock III (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) - -```java -public int maxProfit(int[] prices) { - int firstBuy = Integer.MIN_VALUE, firstSell = 0; - int secondBuy = Integer.MIN_VALUE, secondSell = 0; - for (int curPrice : prices) { - if (firstBuy < -curPrice) { - firstBuy = -curPrice; - } - if (firstSell < firstBuy + curPrice) { - firstSell = firstBuy + curPrice; - } - if (secondBuy < firstSell - curPrice) { - secondBuy = firstSell - curPrice; - } - if (secondSell < secondBuy + curPrice) { - secondSell = secondBuy + curPrice; - } - } - return secondSell; -} -``` - ### 股票交易 **需要冷却期的股票交易** @@ -3432,6 +3371,60 @@ public int maxProfit(int[] prices) { } ``` +**只能进行两次的股票交易** + +[123. Best Time to Buy and Sell Stock III (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/) + +```java +public int maxProfit(int[] prices) { + int firstBuy = Integer.MIN_VALUE, firstSell = 0; + int secondBuy = Integer.MIN_VALUE, secondSell = 0; + for (int curPrice : prices) { + if (firstBuy < -curPrice) { + firstBuy = -curPrice; + } + if (firstSell < firstBuy + curPrice) { + firstSell = firstBuy + curPrice; + } + if (secondBuy < firstSell - curPrice) { + secondBuy = firstSell - curPrice; + } + if (secondSell < secondBuy + curPrice) { + secondSell = secondBuy + curPrice; + } + } + return secondSell; +} +``` + +**只能进行 k 次的股票交易** + +[188. Best Time to Buy and Sell Stock IV (Hard)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/) + +```java +public int maxProfit(int k, int[] prices) { + int n = prices.length; + if (k >= n / 2) { // 这种情况下该问题退化为普通的股票交易问题 + int maxProfit = 0; + for (int i = 1; i < n; i++) { + if (prices[i] > prices[i - 1]) { + maxProfit += prices[i] - prices[i - 1]; + } + } + return maxProfit; + } + int[][] maxProfit = new int[k + 1][n]; + for (int i = 1; i <= k; i++) { + int localMax = maxProfit[i - 1][0] - prices[0]; + for (int j = 1; j < n; j++) { + maxProfit[i][j] = Math.max(maxProfit[i][j - 1], prices[j] + localMax); + localMax = Math.max(localMax, maxProfit[i - 1][j] - prices[j]); + } + } + return maxProfit[k][n - 1]; +} +``` + ### 字符串编辑 **删除两个字符串的字符使它们相等** @@ -3450,11 +3443,8 @@ Explanation: You need one step to make "sea" to "ea" and another step to make "e public int minDistance(String word1, String word2) { int m = word1.length(), n = word2.length(); int[][] dp = new int[m + 1][n + 1]; - for (int i = 0; i <= m; i++) { - for (int j = 0; j <= n; j++) { - if (i == 0 || j == 0) { - continue; - } + for (int i = 1; i <= m; i++) { + for (int j = 1; j <= n; j++) { if (word1.charAt(i - 1) == word2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { @@ -3612,7 +3602,7 @@ public int countPrimes(int n) { ```java int gcd(int a, int b) { - return b == 0 ? a : gcd(b, a% b); + return b == 0 ? a : gcd(b, a % b); } ``` @@ -3683,7 +3673,7 @@ public String convertToBase7(int num) { } ``` -Java 中 static String toString(int num, int radix) 可以将一个整数转换为 redix 进制表示的字符串。 +Java 中 static String toString(int num, int radix) 可以将一个整数转换为 radix 进制表示的字符串。 ```java public String convertToBase7(int num) { @@ -6413,7 +6403,6 @@ public int maxChunksToSorted(int[] arr) { } ``` - ## 图 ### 二分图 @@ -6630,6 +6619,7 @@ public int[] findRedundantConnection(int[][] edges) { } private class UF { + private int[] id; UF(int N) { @@ -6675,7 +6665,7 @@ x ^ x = 0 x & x = x x | x = x ``` - 利用 x ^ 1s = \~x 的特点,可以将位级表示翻转;利用 x ^ x = 0 的特点,可以将三个数中重复的两个数去除,只留下另一个数。 -- 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask :00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。 +- 利用 x & 0s = 0 和 x & 1s = x 的特点,可以实现掩码操作。一个数 num 与 mask:00111100 进行位与操作,只保留 num 中与 mask 的 1 部分相对应的位。 - 利用 x | 0s = x 和 x | 1s = 1s 的特点,可以实现设值操作。一个数 num 与 mask:00111100 进行位或操作,将 num 中与 mask 的 1 部分相对应的位都设置为 1。 位与运算技巧: @@ -6920,7 +6910,6 @@ public boolean isPowerOfFour(int num) { } ``` - **判断一个数的位级表示是否不会出现连续的 0 和 1** [693. Binary Number with Alternating Bits (Easy)](https://leetcode.com/problems/binary-number-with-alternating-bits/description/) diff --git a/notes/Linux.md b/notes/Linux.md index 14d3b317..73a2e9ec 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -129,15 +129,16 @@ info 与 man 类似,但是 info 将文档分成一个个页面,每个页面 /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin ``` -env 命令可以获取当前终端的环境变量。 - ## sudo sudo 允许一般用户使用 root 可执行的命令,不过只有在 /etc/sudoers 配置文件中添加的用户才能使用该指令。 ## 包管理工具 -RPM 和 DPKG 为最常见的两类软件包管理工具。RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,随后被 GNU 开源操作系统接受并成为很多 Linux 系统 (RHEL) 的既定软件标准。与 RPM 进行竞争的是基于 Debian 操作系统 (UBUNTU) 的 DEB 软件包管理工具 DPKG,全称为 Debian Package,功能方面与 RPM 相似。 +RPM 和 DPKG 为最常见的两类软件包管理工具: + +- RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,随后被 GNU 开源操作系统接受并成为很多 Linux 系统 (RHEL) 的既定软件标准。 +- 与 RPM 进行竞争的是基于 Debian 操作系统 (Ubuntu) 的 DEB 软件包管理工具 DPKG,全称为 Debian Package,功能方面与 RPM 相似。 YUM 基于 RPM,具有依赖管理功能,并具有软件升级的功能。 @@ -194,13 +195,13 @@ IDE(ATA)全称 Advanced Technology Attachment,接口速度最大为 133MB/ ### 2. SATA -SATA 全称 Serial ATA,也就是使用串口的 ATA 接口,因抗干扰性强,且对数据线的长度要求比 ATA 低很多,支持热插拔等功能,SATA-II 的接口速度为 300MiB/s,而新的 SATA-III 标准可达到 600MiB/s 的传输速度。SATA 的数据线也比 ATA 的细得多,有利于机箱内的空气流通,整理线材也比较方便。 +SATA 全称 Serial ATA,也就是使用串口的 ATA 接口,抗干扰性强,且对数据线的长度要求比 ATA 低很多,支持热插拔等功能。SATA-II 的接口速度为 300MiB/s,而新的 SATA-III 标准可达到 600MiB/s 的传输速度。SATA 的数据线也比 ATA 的细得多,有利于机箱内的空气流通,整理线材也比较方便。

### 3. SCSI -SCSI 全称是 Small Computer System Interface(小型机系统接口),经历多代的发展,从早期的 SCSI-II,到目前的 Ultra320 SCSI 以及 Fiber-Channel(光纤通道),接口型式也多种多样。SCSI 硬盘广为工作站级个人电脑以及服务器所使用,因此会使用较为先进的技术,如碟片转速 15000rpm 的高转速,且资料传输时 CPU 占用率较低,但是单价也比相同容量的 ATA 及 SATA 硬盘更加昂贵。 +SCSI 全称是 Small Computer System Interface(小型机系统接口),经历多代的发展,从早期的 SCSI-II 到目前的 Ultra320 SCSI 以及 Fiber-Channel(光纤通道),接口型式也多种多样。SCSI 硬盘广为工作站级个人电脑以及服务器所使用,因此会使用较为先进的技术,如碟片转速 15000rpm 的高转速,且传输时 CPU 占用率较低,但是单价也比相同容量的 ATA 及 SATA 硬盘更加昂贵。

@@ -229,7 +230,7 @@ Linux 中每个硬件都被当做一个文件,包括磁盘。磁盘以磁盘 MBR 中,第一个扇区最重要,里面有主要开机记录(Master boot record, MBR)及分区表(partition table),其中主要开机记录占 446 bytes,分区表占 64 bytes。 -分区表只有 64 bytes,最多只能存储 4 个分区,这 4 个分区为主分区(Primary)和扩展分区(Extended)。其中扩展分区只有一个,它将其它扇区用来记录分区表,因此通过扩展分区可以分出更多分区,这些分区称为逻辑分区。 +分区表只有 64 bytes,最多只能存储 4 个分区,这 4 个分区为主分区(Primary)和扩展分区(Extended)。其中扩展分区只有一个,它使用其它扇区用记录额外的分区表,因此通过扩展分区可以分出更多分区,这些分区称为逻辑分区。 Linux 也把分区当成文件,分区文件的命名方式为:磁盘文件名 + 编号,例如 /dev/sda1。注意,逻辑分区的编号从 5 开始。 @@ -251,10 +252,10 @@ MBR 不支持 2.2 TB 以上的硬盘,GPT 则最多支持到 233 TB BIOS(Basic Input/Output System,基本输入输出系统),它是一个固件(嵌入在硬件中的软件),BIOS 程序存放在断电后内容不会丢失的只读内存中。 -BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可以开机的磁盘,并读取磁盘第一个扇区的主要开机记录(MBR),由主要开机记录(MBR)执行其中的开机管理程序,这个开机管理程序会加载操作系统的核心文件。 -

+BIOS 是开机的时候计算机执行的第一个程序,这个程序知道可以开机的磁盘,并读取磁盘第一个扇区的主要开机记录(MBR),由主要开机记录(MBR)执行其中的开机管理程序,这个开机管理程序会加载操作系统的核心文件。 + 主要开机记录(MBR)中的开机管理程序提供以下功能:选单、载入核心文件以及转交其它开机管理程序。转交这个功能可以用来实现了多重引导,只需要将另一个操作系统的开机管理程序安装在其它分区的启动扇区上,在启动开机管理程序时,就可以通过选单选择启动当前的操作系统或者转交给其它开机管理程序从而启动另一个操作系统。 下图中,第一扇区的主要开机记录(MBR)中的开机管理程序提供了两个选单:M1、M2,M1 指向了 Windows 操作系统,而 M2 指向其它分区的启动扇区,里面包含了另外一个开机管理程序,提供了一个指向 Linux 的选单。 @@ -283,11 +284,10 @@ BIOS 不可以读取 GPT 分区表,而 UEFI 可以。 除此之外还包括: - superblock:记录文件系统的整体信息,包括 inode 和 block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等; -- block bitmap:记录 block 是否被使用的位域; +- block bitmap:记录 block 是否被使用的位域。

- ## 文件读取 对于 Ext2 文件系统,当要读取一个文件的内容时,先在 inode 中去查找文件内容所在的所有 block,然后把所有 block 的内容读出来。 @@ -1169,7 +1169,7 @@ dmtsai lines: 5 columns: 9 | S | interruptible sleep (waiting for an event to complete) | | Z | zombie (terminated but not reaped by its parent) | | T | stopped (either by a job control signal or because it is being traced) | - +

## SIGCHLD @@ -1179,12 +1179,12 @@ dmtsai lines: 5 columns: 9 - 得到 SIGCHLD 信号; - waitpid() 或者 wait() 调用会返回。 -

- 其中子进程发送的 SIGCHLD 信号包含了子进程的信息,包含了进程 ID、进程状态、进程使用 CPU 的时间等。 在子进程退出时,它的进程描述符不会立即释放,这是为了让父进程得到子进程信息,父进程通过 wait() 和 waitpid() 来获得一个已经退出的子进程的信息。 +

+ ## wait() ```c diff --git a/notes/Redis.md b/notes/Redis.md index 8f231382..629fcdd8 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -549,7 +549,7 @@ def main(): # 十二、Sentinel -Sentinel(哨兵)可以监听主服务器,并在主服务器进入下线状态时,自动从从服务器中选举出新的主服务器。 +Sentinel(哨兵)可以监听集群中的服务器,并在主服务器进入下线状态时,自动从从服务器中选举出新的主服务器。 # 十三、分片 diff --git a/notes/分布式.md b/notes/分布式.md index c048b43e..e98f2860 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -19,10 +19,11 @@ * [五、Paxos](#五paxos) * [执行过程](#执行过程) * [约束条件](#约束条件) -* [五、Raft](#五raft) +* [六、Raft](#六raft) * [单个 Candidate 的竞选](#单个-candidate-的竞选) * [多个 Candidate 竞选](#多个-candidate-竞选) - * [日志复制](#日志复制) + * [数据同步](#数据同步) +* [参考](#参考) @@ -35,7 +36,7 @@ - 互斥量为 1 表示有其它进程在使用锁,此时处于锁定状态; - 互斥量为 0 表示未锁定状态。 -1 和 0 可以用一个整型值表示,也可以用某个数据存在或者不存在表示,存在表示互斥量为 1。 +1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示,存在表示互斥量为 1。 ## 数据库的唯一索引 @@ -43,7 +44,7 @@ 存在以下几个问题: -- 锁没有失效时间,解锁失败的话其它进程无法再获得锁。 +- 锁没有失效时间,解锁失败的话其它进程无法再获得该锁。 - 只能是非阻塞锁,插入失败直接就报错了,无法重试。 - 不可重入,已经获得锁的进程也必须重新获取锁。 @@ -59,7 +60,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时仍然可用。 -- 尝试从 N 个相互独立 Redis 实例获取锁,如果一个实例不可用,应该尽快尝试下一个; +- 尝试从 N 个相互独立 Redis 实例获取锁; - 计算获取锁消耗的时间,只有当这个时间小于锁的过期时间,并且从大多数(N / 2 + 1)实例上获取了锁,那么就认为锁获取成功了; - 如果锁获取失败,就到每个实例上释放锁。 @@ -67,7 +68,7 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了 ### 1. Zookeeper 抽象模型 -Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示它的父节点为 /app1。 +Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父节点为 /app1。

@@ -96,21 +97,15 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 -参考: - -- [Distributed locks with Redis](https://redis.io/topics/distlock) -- [浅谈分布式锁](http://www.linkedkeeper.com/detail/blog.action?bid=1023) -- [基于 Zookeeper 的分布式锁](http://www.dengshenyu.com/java/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/10/23/zookeeper-distributed-lock.html) - # 二、分布式事务 -指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。 +指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。 + +例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。 ## 本地消息表 -### 1. 原理 - -本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性。 +本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。 1. 在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。 2. 之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。 @@ -118,23 +113,19 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示

-### 2. 分析 - -本地消息表利用了本地事务来实现分布式事务,并且使用了消息队列来保证最终一致性。 - ## 2PC 两阶段提交(Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。 ### 1. 运行过程 -(一)准备阶段 +#### 1.1 准备阶段 协调者询问参与者事务是否执行成功,参与者发回事务执行结果。

-(二)提交阶段 +#### 1.2 提交阶段 如果事务在每个参与者上都执行成功,事务协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。 @@ -144,28 +135,22 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 ### 2. 存在的问题 -(一)同步阻塞 +#### 2.1 同步阻塞 所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作。 -(二)单点问题 +#### 2.2 单点问题 协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其它操作。 -(三)数据不一致 +#### 2.3 数据不一致 在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。 -(四)太过保守 +#### 2.4 太过保守 任意一个节点失败就会导致整个事务失败,没有完善的容错机制。 -参考: - -- [聊聊分布式事务,再说说解决方案](https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html) -- [分布式系统的事务处理](https://coolshell.cn/articles/10910.html) -- [深入理解分布式事务](https://juejin.im/entry/577c6f220a2b5800573492be) - # 三、CAP 分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。 @@ -184,7 +169,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 ## 分区容忍性 @@ -198,16 +183,11 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点表示 可用性和一致性往往是冲突的,很难都使它们同时满足。在多个节点之间进行数据同步时, -* 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; -* 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。 +- 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; +- 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。

-参考: - -- 倪超. 从 Paxos 到 ZooKeeper : 分布式一致性原理与实践 [M]. 电子工业出版社, 2015. -- [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) - # 四、BASE BASE 是基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)三个短语的缩写。 @@ -292,66 +272,69 @@ Acceptor 接收到接受请求时,如果序号大于等于该 Acceptor 承诺 Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性。 -参考: +# 六、Raft -- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) -- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) - -# 五、Raft - -Raft 和 Paxos 类似,但是更容易理解,也更容易实现。 - -Raft 主要是用来竞选主节点。 +Raft 也是分布式一致性协议,主要是用来竞选主节点。 ## 单个 Candidate 的竞选 有三种节点:Follower、Candidate 和 Leader。Leader 会周期性的发送心跳包给 Follower。每个 Follower 都设置了一个随机的竞选超时时间,一般为 150ms\~300ms,如果在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段。 -* 下图表示一个分布式系统的最初阶段,此时只有 Follower,没有 Leader。Follower A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。 +- 下图展示一个分布式系统的最初阶段,此时只有 Follower 没有 Leader。Node A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。

-* 此时 A 发送投票请求给其它所有节点。 +- 此时 Node A 发送投票请求给其它所有节点。

-* 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。 +- 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader。

-* 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。 +- 之后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会重新开始计时。

## 多个 Candidate 竞选 -* 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票,例如下图中 Candidate B 和 Candidate D 都获得两票,因此需要重新开始投票。 +- 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票。例如下图中 Node B 和 Node D 都获得两票,需要重新开始投票。

-* 当重新开始投票时,由于每个节点设置的随机竞选超时时间不同,因此能下一次再次出现多个 Candidate 并获得同样票数的概率很低。 +- 由于每个节点设置的随机竞选超时时间不同,因此下一次再次出现多个 Candidate 并获得同样票数的概率很低。

-## 日志复制 +## 数据同步 -* 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。 +- 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。

-* Leader 会把修改复制到所有 Follower。 +- Leader 会把修改复制到所有 Follower。

-* Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。 +- Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交。

-* 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。 +- 此时 Leader 会通知的所有 Follower 让它们也提交修改,此时所有节点的值达成一致。

-参考: +# 参考 +- 倪超. 从 Paxos 到 ZooKeeper : 分布式一致性原理与实践 [M]. 电子工业出版社, 2015. +- [Distributed locks with Redis](https://redis.io/topics/distlock) +- [浅谈分布式锁](http://www.linkedkeeper.com/detail/blog.action?bid=1023) +- [基于 Zookeeper 的分布式锁](http://www.dengshenyu.com/java/%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F/2017/10/23/zookeeper-distributed-lock.html) - [Raft: Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft) +- [聊聊分布式事务,再说说解决方案](https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html) +- [分布式系统的事务处理](https://coolshell.cn/articles/10910.html) +- [深入理解分布式事务](https://juejin.im/entry/577c6f220a2b5800573492be) +- [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) +- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) +- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 1bac6bbb..d88b6168 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1082,7 +1082,7 @@ false ```java public boolean isNumeric(char[] str) { - if (str == null) + if (str == null || str.length == 0) return false; return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)?"); } @@ -2779,19 +2779,25 @@ public List> dicesSum(int n) { ```java public boolean isContinuous(int[] nums) { + if (nums.length < 5) return false; + Arrays.sort(nums); + + // 统计癞子数量 int cnt = 0; - for (int num : nums) /* 统计癞子数量 */ + for (int num : nums) if (num == 0) cnt++; + // 使用癞子去补全不连续的顺子 for (int i = cnt; i < nums.length - 1; i++) { if (nums[i + 1] == nums[i]) return false; - cnt -= nums[i + 1] - nums[i] - 1; /* 使用癞子去补全不连续的顺子 */ + cnt -= nums[i + 1] - nums[i] - 1; } + return cnt >= 0; } ``` @@ -2824,7 +2830,7 @@ public int LastRemaining_Solution(int n, int m) { ## 题目描述 -可以有一次买入和一次卖出,买入必须在前。求最大收益。 +可以有一次买入和一次卖出,那么买入必须在前。求最大收益。 ## 解题思路 diff --git a/notes/攻击技术.md b/notes/攻击技术.md index d5a735ba..46dd4616 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -207,7 +207,7 @@ ResultSet rs = stmt.executeQuery(); 拒绝服务攻击(denial-of-service attack,DoS),亦称洪水攻击,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。 -分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用网络上两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。 +分布式拒绝服务攻击(distributed denial-of-service attack,DDoS),指攻击者使用两个或以上被攻陷的电脑作为“僵尸”向特定的目标发动“拒绝服务”式攻击。 # 参考资料 diff --git a/notes/构建工具.md b/notes/构建工具.md index c0e4acd5..ce157934 100644 --- a/notes/构建工具.md +++ b/notes/构建工具.md @@ -15,7 +15,7 @@ ## 运行单元测试 -不再需要在项目代码中添加测试代码,从而污染项目代码。 +不再需要在项目代码中添加测试代码,从而避免了污染项目代码。 ## 将源代码转化为可执行文件 diff --git a/notes/消息队列.md b/notes/消息队列.md index c5687e8a..209d962a 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -9,6 +9,7 @@ * [三、可靠性](#三可靠性) * [发送端的可靠性](#发送端的可靠性) * [接收端的可靠性](#接收端的可靠性) +* [参考资料](#参考资料) @@ -29,15 +30,10 @@ 发布与订阅模式和观察者模式有以下不同: - 观察者模式中,观察者和主题都知道对方的存在;而在发布与订阅模式中,发布者与订阅者不知道对方的存在,它们之间通过频道进行通信。 -- 观察者模式是同步的,当事件触发时,主题会去调用观察者的方法,然后等待方法返回;而发布与订阅模式是异步的,发布者向频道发送一个消息之后,就不需要关心订阅者何时去订阅这个消息。 +- 观察者模式是同步的,当事件触发时,主题会调用观察者的方法,然后等待方法返回;而发布与订阅模式是异步的,发布者向频道发送一个消息之后,就不需要关心订阅者何时去订阅这个消息,可以立即返回。

-参考: - -- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/) -- [消息队列中点对点与发布订阅区别](https://blog.csdn.net/lizhitao/article/details/47723105) - # 二、使用场景 ## 异步处理 @@ -78,3 +74,8 @@ - 保证接收端处理消息的业务逻辑具有幂等性:只要具有幂等性,那么消费多少次消息,最后处理的结果都是一样的。 - 保证消息具有唯一编号,并使用一张日志表来记录已经消费的消息编号。 + +# 参考资料 + +- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/) +- [消息队列中点对点与发布订阅区别](https://blog.csdn.net/lizhitao/article/details/47723105) diff --git a/notes/算法.md b/notes/算法.md index 30467b42..a9f9e689 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -23,7 +23,7 @@ * [五、栈和队列](#五栈和队列) * [栈](#栈) * [队列](#队列) -* [六、查找](#六查找) +* [六、符号表](#六符号表) * [初级实现](#初级实现) * [二叉查找树](#二叉查找树) * [2-3 查找树](#2-3-查找树) @@ -507,7 +507,7 @@ public class QuickSort> extends Sort { 取 a[l] 作为切分元素,然后从数组的左端向右扫描直到找到第一个大于等于它的元素,再从数组的右端向左扫描找到第一个小于等于它的元素,交换这两个元素。不断进行这个过程,就可以保证左指针 i 的左侧元素都不大于切分元素,右指针 j 的右侧元素都不小于切分元素。当两个指针相遇时,将切分元素 a[l] 和 a[j] 交换位置。 -

+

```java private int partition(T[] nums, int l, int h) { @@ -770,7 +770,7 @@ public class HeapSort> extends Sort { | 算法 | 稳定 | 时间复杂度 | 空间复杂度 | 备注 | | :---: | :---: |:---: | :---: | :---: | -| 选择排序 | √| N2 | 1 | | +| 选择排序 | × | N2 | 1 | | | 冒泡排序 | √ | N2 | 1 | | | 插入排序 | √ | N \~ N2 | 1 | 时间复杂度和初始顺序有关 | | 希尔排序 | × | N 的若干倍乘于递增序列的长度 | 1 | | @@ -1290,7 +1290,7 @@ public class ListQueue implements MyQueue { -# 六、查找 +# 六、符号表 符号表(Symbol Table)是一种存储键值对的数据结构,可以支持快速查找操作。 @@ -1411,9 +1411,9 @@ public class ListUnorderedST implements UnorderedST { 使用一对平行数组,一个存储键一个存储值。 -rank() 方法至关重要,当键在表中时,它能够知道该键的位置;当键不在表中时,它也能知道在何处插入新键。 +二分查找的 rank() 方法至关重要,当键在表中时,它能够知道该键的位置;当键不在表中时,它也能知道在何处插入新键。 -复杂度:二分查找最多需要 logN+1 次比较,使用二分查找实现的符号表的查找操作所需要的时间最多是对数级别的。但是插入操作需要移动数组元素,是线性级别的。 +二分查找最多需要 logN+1 次比较,使用二分查找实现的符号表的查找操作所需要的时间最多是对数级别的。但是插入操作需要移动数组元素,是线性级别的。 ```java public class BinarySearchOrderedST, Value> implements OrderedST { @@ -2254,7 +2254,7 @@ from H1 to H3 - c : 40 - d : 80 -可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码能让出现频率最高的字符的编码最短,从而保证整体的编码长度最短。 +可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码采用了贪心策略,使出现频率最高的字符的编码最短,从而保证整体的编码长度最短。 首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index 805764a9..b6a3ddf5 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -68,7 +68,7 @@ 应用服务器只要不具有状态,那么就可以很容易地通过负载均衡器向集群中添加新的服务器。 -关系型数据库的伸缩性通过 Sharding 来实现,将数据按一定的规则分布到不同的节点上,从而解决单台存储服务器存储空间限制。 +关系型数据库的伸缩性通过 Sharding 来实现,将数据按一定的规则分布到不同的节点上,从而解决单台存储服务器的存储空间限制。 对于非关系型数据库,它们天生就是为海量数据而诞生,对伸缩性的支持特别好。 @@ -78,7 +78,7 @@ 实现可扩展主要有两种方式: -- 使用消息队列进行解耦,应用之间通过消息传递的方式进行通信; +- 使用消息队列进行解耦,应用之间通过消息传递进行通信; - 使用分布式服务将业务和可复用的服务分离开来,业务使用分布式服务框架调用可复用的服务。新增的产品可以通过调用可复用的服务来实现业务逻辑,对其它产品没有影响。 # 四、可用性 @@ -87,7 +87,7 @@ 保证高可用的主要手段是使用冗余,当某个服务器故障时就请求其它服务器。 -应用服务器的冗余比较容易实现,只要保证应用服务器不具有状态,那么某个应用服务器故障时,负载均衡器将该应用服务器原先的用户请求转发到另一个应用服务器上不会对用户有任何影响。 +应用服务器的冗余比较容易实现,只要保证应用服务器不具有状态,那么某个应用服务器故障时,负载均衡器将该应用服务器原先的用户请求转发到另一个应用服务器上,不会对用户有任何影响。 存储服务器的冗余需要使用主从复制来实现,当主服务器故障时,需要提升从服务器为主服务器,这个过程称为切换。 @@ -97,7 +97,7 @@ ## 服务降级 -服务器降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。 +服务降级是系统为了应对大量的请求,主动关闭部分功能,从而保证核心功能可用。 # 五、安全性 diff --git a/notes/缓存.md b/notes/缓存.md index 9a9f2810..ed834253 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -6,6 +6,7 @@ * [五、缓存问题](#五缓存问题) * [六、数据分布](#六数据分布) * [七、一致性哈希](#七一致性哈希) +* [参考资料](#参考资料) @@ -29,10 +30,6 @@ - LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最远的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 -参考资料: - -- [缓存那些事](https://tech.meituan.com/cache_about.html) - # 二、LRU 以下是一个基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: @@ -143,10 +140,6 @@ public class LRU implements Iterable { } ``` -源代码: - -- [CyC2018/Algorithm](https://github.com/CyC2018/Algorithm/tree/master/Caching) - # 三、缓存位置 ## 浏览器 @@ -169,7 +162,7 @@ public class LRU implements Iterable { 使用 Redis、Memcache 等分布式缓存将数据缓存在分布式缓存系统中。 -相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存。而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 +相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 ## 数据库缓存 @@ -177,7 +170,7 @@ MySQL 等数据库管理系统具有自己的查询缓存机制来提高 SQL 查 # 四、CDN -内容分发网络(Content distribution network,CDN)是一种通过互连的网络系统,利用更靠近用户的服务器更快更可靠地将 HTML、CSS、JavaScript、音乐、图片、视频等静态资源分发给用户。 +内容分发网络(Content distribution network,CDN)是一种互连的网络系统,它利用更靠近用户的服务器从而更快更可靠地将 HTML、CSS、JavaScript、音乐、图片、视频等静态资源分发给用户。 CDN 主要有以下优点: @@ -187,11 +180,6 @@ CDN 主要有以下优点:

-参考资料: - -- [内容分发网络](https://zh.wikipedia.org/wiki/%E5%85%A7%E5%AE%B9%E5%82%B3%E9%81%9E%E7%B6%B2%E8%B7%AF) -- [How Aspiration CDN helps to improve your website loading speed?](https://www.aspirationhosting.com/aspiration-cdn/) - # 五、缓存问题 ## 缓存穿透 @@ -213,7 +201,7 @@ CDN 主要有以下优点: - 为了防止缓存在同一时间大面积过期导致的缓存雪崩,可以通过观察用户行为,合理设置缓存过期时间来实现; - 为了防止缓存服务器宕机出现的缓存雪崩,可以使用分布式缓存,分布式缓存中每一个节点只缓存部分的数据,当某个节点宕机时可以保证其它节点的缓存仍然可用。 -- 也可以在进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 +- 也可以进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。 ## 缓存一致性 @@ -243,10 +231,6 @@ CDN 主要有以下优点: - 能保持数据原有的顺序; - 并且能够准确控制每台服务器存储的数据量,从而使得存储空间的利用率最大。 -参考资料: - -- 大规模分布式存储系统 - # 七、一致性哈希 Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据失效的问题。 @@ -267,6 +251,10 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了 数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得大,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 -参考资料: +# 参考资料 +- 大规模分布式存储系统 +- [缓存那些事](https://tech.meituan.com/cache_about.html) - [一致性哈希算法](https://my.oschina.net/jayhu/blog/732849) +- [内容分发网络](https://zh.wikipedia.org/wiki/%E5%85%A7%E5%AE%B9%E5%82%B3%E9%81%9E%E7%B6%B2%E8%B7%AF) +- [How Aspiration CDN helps to improve your website loading speed?](https://www.aspirationhosting.com/aspiration-cdn/) diff --git a/notes/设计模式.md b/notes/设计模式.md index b8f4dc9b..531595e3 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -60,9 +60,9 @@ (一)懒汉式-线程不安全 -以下实现中,私有静态变量 uniqueInstance 被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 +以下实现中,私有静态变量 uniqueInstance 被延迟实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 -这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么多个线程会执行 `uniqueInstance = new Singleton();` 语句,这将导致多次实例化 uniqueInstance。 +这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么会有多个线程执行 `uniqueInstance = new Singleton();` 语句,这将导致多次实例化 uniqueInstance。 ```java public class Singleton { @@ -81,11 +81,21 @@ public class Singleton { } ``` -(二)懒汉式-线程安全 +(二)饿汉式-线程安全 -只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。 +线程不安全问题主要是由于 uniqueInstance 被多次实例化,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。 -但是这样有一个问题,就是当一个线程进入该方法之后,其它线程试图进入该方法都必须等待,因此性能上有一定的损耗。 +但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。 + +```java +private static Singleton uniqueInstance = new Singleton(); +``` + +(三)懒汉式-线程安全 + +只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了多次实例化 uniqueInstance 的问题。 + +但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,因此性能上有一定的损耗。 ```java public static synchronized Singleton getUniqueInstance() { @@ -96,16 +106,6 @@ public static synchronized Singleton getUniqueInstance() { } ``` -(三)饿汉式-线程安全 - -线程不安全问题主要是由于 uniqueInstance 被实例化了多次,如果 uniqueInstance 采用直接实例化的话,就不会被实例化多次,也就不会产生线程不安全问题。 - -但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。 - -```java -private static Singleton uniqueInstance = new Singleton(); -``` - (四)双重校验锁-线程安全 uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。 @@ -175,7 +175,7 @@ public class Singleton { } ``` -(五)枚举实现 +(六)枚举实现 这是单例模式的最佳实践,它实现简单,并且在面对复杂的序列化或者反射攻击的时候,能够防止实例化多次。 @@ -231,27 +231,9 @@ public class Singleton implements Serializable { 简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 -

- 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。因为客户类往往有多个,如果不使用简单工厂,所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 -如果存在下面这种代码,就需要使用简单工厂将对象实例化的部分放到简单工厂中。 - -```java -public class Client { - public static void main(String[] args) { - int type = 1; - Product product; - if (type == 1) { - product = new ConcreteProduct1(); - } else if (type == 2) { - product = new ConcreteProduct2(); - } else { - product = new ConcreteProduct(); - } - } -} -``` +

### 实现 @@ -275,6 +257,27 @@ public class ConcreteProduct2 implements Product { } ``` +以下的 Client 类中包含了实例化的代码,这是一种错误的实现,如果在客户类中存在实例化代码,就需要将代码放到简单工厂中。 + +```java +public class Client { + public static void main(String[] args) { + int type = 1; + Product product; + if (type == 1) { + product = new ConcreteProduct1(); + } else if (type == 2) { + product = new ConcreteProduct2(); + } else { + product = new ConcreteProduct(); + } + // do something with the product + } +} +``` + +以下的 SimpleFactory 是简单工厂实现,它被所有需要进行实例化的客户类调用。 + ```java public class SimpleFactory { public Product createProduct(int type) { @@ -293,6 +296,7 @@ public class Client { public static void main(String[] args) { SimpleFactory simpleFactory = new SimpleFactory(); Product product = simpleFactory.createProduct(1); + // do something with the product } } ``` @@ -2906,7 +2910,7 @@ Java 利用缓存来加速大量小对象的访问时间。 - 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。 - 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。 - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 -- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数,比如智能智能;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 +- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 9b59e43d..203c7ebf 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -37,6 +37,7 @@ ```java public class Person { + private String name; private int gender; private int age; @@ -63,17 +64,20 @@ public class Person { 继承实现了 **IS-A** 关系,例如 Cat 和 Animal 就是一种 IS-A 关系,因此 Cat 可以继承自 Animal,从而获得 Animal 非 private 的属性和方法。 +继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。 + Cat 可以当做 Animal 来使用,也就是说可以使用 Animal 引用 Cat 对象。父类引用指向子类对象称为 **向上转型** 。 ```java Animal animal = new Cat(); ``` -继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。 - ## 多态 -多态分为编译时多态和运行时多态。编译时多态主要指方法的重载,运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定。 +多态分为编译时多态和运行时多态: + +- 编译时多态主要指方法的重载 +- 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定 运行时多态有三个条件: @@ -116,7 +120,7 @@ public class Music { # 二、类图 -以下类图使用 [PlantUML](https://www.planttext.com/) 绘制,更多语法及使用请参考:http://plantuml.com/ +以下类图使用 [PlantUML](https://www.planttext.com/) 绘制,更多语法及使用请参考:http://plantuml.com/ 。 ## 泛化关系 (Generalization) @@ -327,7 +331,7 @@ Vihicle .. N ### 2. 合成复用原则 -尽量使用对象组合,而不是继承来达到复用的目的。 +尽量使用对象组合,而不是通过继承来达到复用的目的。 ### 3. 共同封闭原则 @@ -349,3 +353,4 @@ Vihicle .. N - [看懂 UML 类图和时序图](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization) - [UML 系列——时序图(顺序图)sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html) - [面向对象编程三大特性 ------ 封装、继承、多态](http://blog.csdn.net/jianyuerensheng/article/details/51602015) + From a8104d3f5e7df44fe56b55e16b07639d5811e381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Sat, 25 Aug 2018 23:30:03 +0800 Subject: [PATCH 021/136] Update README.md --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d511fa7c..27edaf24 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ -## :pencil2: 算法 +### :pencil2: 算法 - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) @@ -25,7 +25,7 @@ 排序、并查集、栈和队列、红黑树、散列表。 -## :computer: 操作系统 +### :computer: 操作系统 - [计算机操作系统](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机操作系统.md) @@ -35,7 +35,7 @@ 基本实现原理以及基本操作。 -## :cloud: 网络 +### :cloud: 网络 - [计算机网络](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/计算机网络.md) @@ -49,7 +49,7 @@ I/O 模型、I/O 多路复用。 -## :couple: 面向对象 +### :couple: 面向对象 - [设计模式](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/设计模式.md) @@ -59,7 +59,7 @@ 三大原则(继承、封装、多态)、类图、设计原则。 -## :floppy_disk: 数据库 +### :floppy_disk: 数据库 - [数据库系统原理](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/数据库系统原理.md) @@ -81,7 +81,7 @@ 五种数据类型、字典和跳跃表数据结构、使用场景、和 Memcache 的比较、淘汰策略、持久化、文件事件的 Reactor 模式、复制。 -## :coffee: Java +### :coffee: Java - [Java 基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Java%20基础.md) @@ -103,7 +103,7 @@ NIO 的原理以及实例。 -## :bulb: 系统设计 +### :bulb: 系统设计 - [系统设计基础](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/系统设计基础.md) @@ -129,7 +129,7 @@ 消息处理模型、使用场景、可靠性 -## :hammer: 工具 +### :hammer: 工具 - [Git](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/Git.md) @@ -147,7 +147,7 @@ 构建工具的基本概念、主流构建工具介绍。 -## :speak_no_evil: 编码实践 +### :speak_no_evil: 编码实践 - [重构](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/重构.md) @@ -161,9 +161,9 @@ Google 开源项目的代码风格规范。 -## :memo: 后记 +### :memo: 后记 -### About +#### About 这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。 @@ -171,7 +171,7 @@ [BOOKLIST](https://github.com/CyC2018/Interview-Notebook/blob/master/BOOKLIST.md),这个书单是笔者至今看的一些比较好的技术书籍,虽然没有全都看完,但每本书多多少少都看了一部分。 -### How To Contribute +#### How To Contribute 笔记内容是笔者一个字一个字打上去的,难免会有一些笔误,如果发现笔误可直接在相应文档进行编辑修改。 @@ -179,7 +179,7 @@ 欢迎在 Issue 中提交对本仓库的改进建议~ -### Typesetting +#### Typesetting 笔记内容按照 [中文文案排版指北](http://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版,以保证内容的可读性。 @@ -187,7 +187,7 @@ 笔者将自己实现的文档排版功能提取出来,放在 Github Page 中,无需下载安装即可免费使用:[Text-Typesetting](https://github.com/CyC2018/Markdown-Typesetting)。 -### Uploading +#### Uploading 笔者在本地使用为知笔记软件进行书写,为了方便将本地笔记内容上传到 Github 上,实现了一整套自动化上传方案,包括文本文件的导出、提取图片、Markdown 文档转换、Git 同步。 @@ -195,15 +195,15 @@ 笔者将自己实现文档转换功能提取出来,方便大家在需要将本地 Markdown 上传到 Github,或者制作项目 README 文档时生成目录时使用:[GFM-Converter](https://github.com/CyC2018/GFM-Converter)。 -### Statement +#### Statement 本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) -### Logo +#### Logo Power by [logomakr](https://logomakr.com/). -### Acknowledgements +#### Acknowledgements 感谢以下人员对本仓库做出的贡献,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与笔者联系。 @@ -229,7 +229,7 @@ Power by [logomakr](https://logomakr.com/). -### License +#### License 在对本作品进行演绎时,请署名并以相同方式共享。 From b75f85c61731f3e128504bcbe0c0ce55294836b1 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 13:12:11 +0800 Subject: [PATCH 022/136] auto commit --- notes/MySQL.md | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/notes/MySQL.md b/notes/MySQL.md index bb465ff3..04b6ea61 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -4,7 +4,7 @@ * [MySQL 索引](#mysql-索引) * [索引优化](#索引优化) * [索引的优点](#索引的优点) - * [索引的使用场景](#索引的使用场景) + * [索引的使用条件](#索引的使用条件) * [二、查询性能优化](#二查询性能优化) * [使用 Explain 进行分析](#使用-explain-进行分析) * [优化数据访问](#优化数据访问) @@ -58,13 +58,13 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具 平衡树查找操作的时间复杂度等于树高 h,而树高大致为 O(h)=O(logdN),其中 d 为每个节点的出度。 -红黑树的出度为 2,而 B+ Tree 的出度一般都非常大,所以红黑树的树高 h 很明显比 B+ Tree 大非常多,检索的次数也就更多。 +红黑树的出度为 2,而 B+ Tree 的出度一般都非常大,所以红黑树的树高 h 很明显比 B+ Tree 大非常多,查找的次数也就更多。 -(二)利用计算机预读特性 +(二)利用磁盘预读特性 -为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道,并且只需要很短的旋转时间,因此速度会非常快。 +为了减少磁盘 I/O,磁盘往往不是严格按需读取,而是每次都会预读。预读过程中,磁盘进行顺序读取,顺序读取不需要进行磁盘寻道,并且只需要很短的旋转时间,速度会非常快。 -操作系统一般将内存和磁盘分割成固态大小的块,每一块称为一页,内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小,使得一次 I/O 就能完全载入一个节点,并且可以利用预读特性,相邻的节点也能够被预先载入。 +操作系统一般将内存和磁盘分割成固态大小的块,每一块称为一页,内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小,使得一次 I/O 就能完全载入一个节点。并且可以利用预读特性,相邻的节点也能够被预先载入。 ## MySQL 索引 @@ -74,15 +74,15 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具 是大多数 MySQL 存储引擎的默认索引类型。 -因为不再需要进行全表扫描,只需要对树进行搜索即可,因此查找速度快很多。除了用于查找,还可以用于排序和分组。 +因为不再需要进行全表扫描,只需要对树进行搜索即可,所以查找速度快很多。 + +除了用于查找,还可以用于排序和分组。 可以指定多个列作为索引列,多个索引列共同组成键。 适用于全键值、键值范围和键前缀查找,其中键前缀查找只适用于最左前缀查找。如果不是按照索引列的顺序进行查找,则无法使用索引。 -InnoDB 的 B+Tree 索引分为主索引和辅助索引。 - -主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。 +InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。

@@ -92,7 +92,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。 ### 2. 哈希索引 -哈希索引能以 O(1) 时间进行查找,但是失去了有序性,它具有以下限制: +哈希索引能以 O(1) 时间进行查找,但是失去了有序性: - 无法用于排序与分组; - 只支持精确查找,无法用于部分查找和范围查找。 @@ -101,9 +101,11 @@ InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”,当 ### 3. 全文索引 -MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较是否相等。查找条件使用 MATCH AGAINST,而不是普通的 WHERE。 +MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较是否相等。 -全文索引一般使用倒排索引实现,它记录着关键词到其所在文档的映射。 +查找条件使用 MATCH AGAINST,而不是普通的 WHERE。 + +全文索引使用倒排索引实现,它记录着关键词到其所在文档的映射。 InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引。 @@ -136,7 +138,9 @@ WHERE actor_id = 1 AND film_id = 1; ### 3. 索引列的顺序 -让选择性最强的索引列放在前面,索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,查询效率也越高。 +让选择性最强的索引列放在前面。 + +索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,查询效率也越高。 例如下面显示的结果中 customer_id 的选择性比 staff_id 更高,因此最好把 customer_id 列放在多列索引的前面。 @@ -173,14 +177,16 @@ customer_id_selectivity: 0.0373 - 大大减少了服务器需要扫描的数据行数。 -- 帮助服务器避免进行排序和分组,也就不需要创建临时表(B+Tree 索引是有序的,可以用于 ORDER BY 和 GROUP BY 操作。临时表主要是在排序和分组过程中创建,因为不需要排序和分组,也就不需要创建临时表)。 +- 帮助服务器避免进行排序和分组,以及避免创建临时表(B+Tree 索引是有序的,可以用于 ORDER BY 和 GROUP BY 操作。临时表主要是在排序和分组过程中创建,因为不需要排序和分组,也就不需要创建临时表)。 -- 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,也就将相邻的数据都存储在一起)。 +- 将随机 I/O 变为顺序 I/O(B+Tree 索引是有序的,会将相邻的数据都存储在一起)。 -## 索引的使用场景 +## 索引的使用条件 + +- 对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效; + +- 对于中到大型的表,索引就非常有效; -- 对于非常小的表、大部分情况下简单的全表扫描比建立索引更高效。 -- 对于中到大型的表,索引就非常有效。 - 但是对于特大型的表,建立和维护索引的代价将会随之增长。这种情况下,需要用到一种技术可以直接区分出需要查询的一组数据,而不是一条记录一条记录地匹配,例如可以使用分区技术。 # 二、查询性能优化 @@ -214,7 +220,7 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai 一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。 ```sql -DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); +DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); ``` ```sql @@ -342,7 +348,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。 -当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓解单个数据库的压力。 +当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓存单个数据库的压力。

From e57025b873e8f330c8a36f9601965e9997e0e4e8 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 15:41:50 +0800 Subject: [PATCH 023/136] auto commit --- notes/Java 基础.md | 2 +- notes/Java 虚拟机.md | 16 +++++----------- notes/MySQL.md | 23 ++++++++++------------- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 44ca873a..1f172f30 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -215,7 +215,7 @@ String s5 = "bbb"; System.out.println(s4 == s5); // true ``` -在 Java 7 之前,字符串常量池被放在运行时常量池中,它属于永久代。而在 Java 7,字符串常量池被移到 Native Method 中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 +在 Java 7 之前,字符串常量池被放在运行时常量池中,它属于永久代。而在 Java 7,字符串常量池被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 - [StackOverflow : What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning) - [深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 1bba557b..edc43e8f 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -38,7 +38,7 @@ ## Java 虚拟机栈 -每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息,从调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。 +每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。

@@ -55,27 +55,21 @@ java -Xss512M HackTheJava ## 本地方法栈 -本地方法一般是用其它语言(C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。 - 本地方法栈与 Java 虚拟机栈类似,它们之间的区别只不过是本地方法栈为本地方法服务。 +本地方法一般是用其它语言(C、C++ 或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序,对待这些方法需要特别处理。 +

## 堆 所有对象都在这里分配内存,是垃圾收集的主要区域("GC 堆")。 -现代的垃圾收集器基本都是采用分代收集算法,针对不同类型的对象采取不同的垃圾回收算法,可以将堆分成两块: +现代的垃圾收集器基本都是采用分代收集算法,其主要的思想是针对不同类型的对象采取不同的垃圾回收算法,可以将堆分成两块: - 新生代(Young Generation) - 老年代(Old Generation) -新生代可以继续划分成以下三个空间: - -- Eden(伊甸园) -- From Survivor(幸存者) -- To Survivor - 堆不需要连续内存,并且可以动态增加其内存,增加失败会抛出 OutOfMemoryError 异常。 可以通过 -Xms 和 -Xmx 两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值。 @@ -104,7 +98,7 @@ Class 文件中的常量池(编译器生成的各种字面量和符号引用 ## 直接内存 -在 JDK 1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。 +在 JDK 1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存(Native 堆),然后通过一个存储在 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。 这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。 diff --git a/notes/MySQL.md b/notes/MySQL.md index 04b6ea61..bf795d34 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -354,17 +354,17 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 ## 垂直切分 -

- 垂直切分是将一张表按列切分成多个表,通常是按照列的关系密集程度进行切分,也可以利用垂直切分将经常被使用的列和不经常被使用的列切分到不同的表中。 在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库、用户数据库等。 +

+ ## Sharding 策略 -- 哈希取模:hash(key) % NUM_DB -- 范围:可以是 ID 范围也可以是时间范围 -- 映射表:使用单独的一个数据库来存储映射关系 +- 哈希取模:hash(key) % N; +- 范围:可以是 ID 范围也可以是时间范围; +- 映射表:使用单独的一个数据库来存储映射关系。 ## Sharding 存在的问题及解决方案 @@ -382,20 +382,15 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 - 为每个分片指定一个 ID 范围 - 分布式 ID 生成器 (如 Twitter 的 Snowflake 算法) -更多内容请参考: - -- [How Sharding Works](https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6) -- [大众点评订单系统分库分表实践](https://tech.meituan.com/dianping_order_db_sharding.html) - # 六、复制 ## 主从复制 主要涉及三个线程:binlog 线程、I/O 线程和 SQL 线程。 -- **binlog 线程** :负责将主服务器上的数据更改写入二进制日志中。 -- **I/O 线程** :负责从主服务器上读取二进制日志,并写入从服务器的中继日志中。 -- **SQL 线程** :负责读取中继日志并重放其中的 SQL 语句。 +- **binlog 线程** :负责将主服务器上的数据更改写入二进制日志(Binary log)中。 +- **I/O 线程** :负责从主服务器上读取二进制日志,并写入从服务器的重放日志(Replay log)中。 +- **SQL 线程** :负责读取重放日志并重放其中的 SQL 语句。

@@ -423,3 +418,5 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 - [SQL Azure Federation – Introduction](http://geekswithblogs.net/shaunxu/archive/2012/01/07/sql-azure-federation-ndash-introduction.aspx "Title of this entry.") - [MySQL 索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html) - [MySQL 性能优化神器 Explain 使用分析](https://segmentfault.com/a/1190000008131735) +- [How Sharding Works](https://medium.com/@jeeyoungk/how-sharding-works-b4dec46b3f6) +- [大众点评订单系统分库分表实践](https://tech.meituan.com/dianping_order_db_sharding.html) From 4a6a3583f0adf864a81dafa51546893dbad71d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Sun, 26 Aug 2018 15:44:44 +0800 Subject: [PATCH 024/136] Update BOOKLIST.md --- BOOKLIST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BOOKLIST.md b/BOOKLIST.md index 4805a7dc..e88ba706 100644 --- a/BOOKLIST.md +++ b/BOOKLIST.md @@ -54,7 +54,7 @@ - [STL 源码剖析](https://book.douban.com/subject/1110934/) - [深度探索 C++ 对象模型](https://book.douban.com/subject/1091086/) -# 网站架构/分布式 +# 系统设计 - [大规模分布式存储系统](https://book.douban.com/subject/25723658/) - [从 Paxos 到 Zookeeper](https://book.douban.com/subject/26292004/) From 1c85575ed1cc2894bae203cb305f6e8c2de3bba9 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 16:17:09 +0800 Subject: [PATCH 025/136] auto commit --- notes/Java 虚拟机.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index edc43e8f..c3ae5889 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -136,8 +136,6 @@ public class ReferenceCountingGC { 通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是存活的,不可达的对象可被回收。 -

- Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容: - 虚拟机栈中引用的对象 @@ -145,6 +143,8 @@ Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC - 方法区中类静态属性引用的对象 - 方法区中的常量引用的对象 +

+ ### 3. 方法区的回收 因为方法区主要存放永久代对象,而永久代对象的回收率比新生代低很多,因此在方法区上进行回收性价比不高。 @@ -165,13 +165,13 @@ Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。但是 try-finally 等方式可以做的更好,并且该方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此最好不要使用。 -当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能通过在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会调用 finalize() 方法。 +当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会调用 finalize() 方法。 ## 引用类型 无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象是否可达,判定对象是否可被回收都与引用有关。 -Java 具有四种强度不同的引用类型。 +Java 提供了四种强度不同的引用类型。 ### 1. 强引用 @@ -280,7 +280,7 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 它的优点是简单高效,对于单个 CPU 环境来说,由于没有线程交互的开销,因此拥有最高的单线程收集效率。 -它是 Client 模式下的默认新生代收集器,因为在用户的桌面应用场景下,分配给虚拟机管理的内存一般来说不会很大。Serial 收集器收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿是可以接受的。 +它是 Client 模式下的默认新生代收集器,因为在该应用场景下,分配给虚拟机管理的内存一般来说不会很大。Serial 收集器收集几十兆甚至一两百兆的新生代停顿时间可以控制在一百多毫秒以内,只要不是太频繁,这点停顿是可以接受的。 ### 2. ParNew 收集器 @@ -298,11 +298,11 @@ Serial 翻译为串行,也就是说它以串行的方式执行。 其它收集器关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而它的目标是达到一个可控制的吞吐量,它被称为“吞吐量优先”收集器。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。 -停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。 +停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。 缩短停顿时间是以牺牲吞吐量和新生代空间来换取的:新生代空间变小,垃圾回收变得频繁,导致吞吐量下降。 -可以通过一个开关参数打卡 GC 自适应的调节策略(GC Ergonomics),就不需要手工指定新生代的大小(-Xmn)、Eden 和 Survivor 区的比例、晋升老年代对象年龄等细节参数了。虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种方式称为 。 +可以通过一个开关参数打开 GC 自适应的调节策略(GC Ergonomics),就不需要手工指定新生代的大小(-Xmn)、Eden 和 Survivor 区的比例、晋升老年代对象年龄等细节参数了。虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。 ### 4. Serial Old 收集器 @@ -372,8 +372,6 @@ G1 把堆划分成多个大小相等的独立区域(Region),新生代和 - 空间整合:整体来看是基于“标记 - 整理”算法实现的收集器,从局部(两个 Region 之间)上来看是基于“复制”算法实现的,这意味着运行期间不会产生内存空间碎片。 - 可预测的停顿:能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在 GC 上的时间不得超过 N 毫秒。 -更详细内容请参考:[Getting Started with the G1 Garbage Collector](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html) - # 三、内存分配与回收策略 ## Minor GC 和 Full GC @@ -738,6 +736,7 @@ public class FileSystemClassLoader extends ClassLoader { - 周志明. 深入理解 Java 虚拟机 [M]. 机械工业出版社, 2011. - [Chapter 2. The Structure of the Java Virtual Machine](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4) - [Jvm memory](https://www.slideshare.net/benewu/jvm-memory) +[Getting Started with the G1 Garbage Collector](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/G1GettingStarted/index.html) - [JNI Part1: Java Native Interface Introduction and “Hello World” application](http://electrofriends.com/articles/jni/jni-part1-java-native-interface/) - [Memory Architecture Of JVM(Runtime Data Areas)](https://hackthejava.wordpress.com/2015/01/09/memory-architecture-by-jvmruntime-data-areas/) - [JVM Run-Time Data Areas](https://www.programcreek.com/2013/04/jvm-run-time-data-areas/) From dce6d0ee3f0605e5553db6d46b15ea0ff58540c6 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 19:57:38 +0800 Subject: [PATCH 026/136] auto commit --- notes/Java 容器.md | 187 ++++++++++++++++++++----------------------- notes/Java 虚拟机.md | 2 +- 2 files changed, 87 insertions(+), 102 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 001f864c..57e5f475 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -126,7 +126,91 @@ public class ArrayList extends AbstractList private static final int DEFAULT_CAPACITY = 10; ``` -### 2. 序列化 +### 2. 扩容 + +添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 `oldCapacity + (oldCapacity >> 1)`,也就是旧容量的 1.5 倍。 + +扩容操作需要调用 `Arrays.copyOf()` 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。 + +```java +public boolean add(E e) { + ensureCapacityInternal(size + 1); // Increments modCount!! + elementData[size++] = e; + return true; +} + +private void ensureCapacityInternal(int minCapacity) { + if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { + minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); + } + ensureExplicitCapacity(minCapacity); +} + +private void ensureExplicitCapacity(int minCapacity) { + modCount++; + // overflow-conscious code + if (minCapacity - elementData.length > 0) + grow(minCapacity); +} + +private void grow(int minCapacity) { + // overflow-conscious code + int oldCapacity = elementData.length; + int newCapacity = oldCapacity + (oldCapacity >> 1); + if (newCapacity - minCapacity < 0) + newCapacity = minCapacity; + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); + // minCapacity is usually close to size, so this is a win: + elementData = Arrays.copyOf(elementData, newCapacity); +} +``` + +### 3. 删除元素 + +需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看出 ArrayList 删除元素的代价是非常高的。 + +```java +public E remove(int index) { + rangeCheck(index); + modCount++; + E oldValue = elementData(index); + int numMoved = size - index - 1; + if (numMoved > 0) + System.arraycopy(elementData, index+1, elementData, index, numMoved); + elementData[--size] = null; // clear to let GC do its work + return oldValue; +} +``` + +### 4. Fail-Fast + +modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。 + +在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。 + +```java +private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException{ + // Write out element count, and any hidden stuff + int expectedModCount = modCount; + s.defaultWriteObject(); + + // Write out size as capacity for behavioural compatibility with clone() + s.writeInt(size); + + // Write out all elements in the proper order. + for (int i=0; i> 1)`,也就是旧容量的 1.5 倍。 - -扩容操作需要调用 `Arrays.copyOf()` 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。 - -```java -public boolean add(E e) { - ensureCapacityInternal(size + 1); // Increments modCount!! - elementData[size++] = e; - return true; -} - -private void ensureCapacityInternal(int minCapacity) { - if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { - minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); - } - ensureExplicitCapacity(minCapacity); -} - -private void ensureExplicitCapacity(int minCapacity) { - modCount++; - // overflow-conscious code - if (minCapacity - elementData.length > 0) - grow(minCapacity); -} - -private void grow(int minCapacity) { - // overflow-conscious code - int oldCapacity = elementData.length; - int newCapacity = oldCapacity + (oldCapacity >> 1); - if (newCapacity - minCapacity < 0) - newCapacity = minCapacity; - if (newCapacity - MAX_ARRAY_SIZE > 0) - newCapacity = hugeCapacity(minCapacity); - // minCapacity is usually close to size, so this is a win: - elementData = Arrays.copyOf(elementData, newCapacity); -} -``` - -### 4. 删除元素 - -需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看出 ArrayList 删除元素的代价是非常高的。 - -```java -public E remove(int index) { - rangeCheck(index); - modCount++; - E oldValue = elementData(index); - int numMoved = size - index - 1; - if (numMoved > 0) - System.arraycopy(elementData, index+1, elementData, index, numMoved); - elementData[--size] = null; // clear to let GC do its work - return oldValue; -} -``` - -### 5. Fail-Fast - -modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。 - -在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。 - -```java -private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException{ - // Write out element count, and any hidden stuff - int expectedModCount = modCount; - s.defaultWriteObject(); - - // Write out size as capacity for behavioural compatibility with clone() - s.writeInt(size); - - // Write out all elements in the proper order. - for (int i=0; i implements Map.Entry { public final String toString() { return getKey() + "=" + getValue(); } - - /** - * This method is invoked whenever the value in an entry is - * overwritten by an invocation of put(k,v) for a key k that's already - * in the HashMap. - */ - void recordAccess(HashMap m) { - } - - /** - * This method is invoked whenever the entry is - * removed from the table. - */ - void recordRemoval(HashMap m) { - } } ``` @@ -929,7 +914,7 @@ JDK 1.8 使用了 CAS 操作来支持更高的并发度,在 CAS 操作失败 public class LinkedHashMap extends HashMap implements Map ``` -内存维护了一个双向链表,用来维护插入顺序或者 LRU 顺序。 +内部维护了一个双向链表,用来维护插入顺序或者 LRU 顺序。 ```java /** diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index c3ae5889..2b565cb5 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -531,7 +531,7 @@ public class Test { - 与类的构造函数(或者说实例构造器 <init>())不同,不需要显式的调用父类的构造器。虚拟机会自动保证在子类的 <clinit>() 方法运行之前,父类的 <clinit>() 方法已经执行结束。因此虚拟机中第一个执行 <clinit>() 方法的类肯定为 java.lang.Object。 -- 由于父类的 <clinit>() 方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作。例如以下代码: +- 由于父类的 <clinit>() 方法先执行,也就意味着父类中定义的静态语句块的执行要优先于子类。例如以下代码: ```java static class Parent { From 322a6c58bfd857dfcd78c6ed291ee001c9dc8ae6 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 20:53:07 +0800 Subject: [PATCH 027/136] auto commit --- notes/Java 基础.md | 76 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 1f172f30..95249103 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -6,7 +6,8 @@ * [概览](#概览) * [不可变的好处](#不可变的好处) * [String, StringBuffer and StringBuilder](#string,-stringbuffer-and-stringbuilder) - * [String.intern()](#stringintern) + * [String Pool](#string-pool) + * [new String("abc")](#new-string"abc") * [三、运算](#三运算) * [参数传递](#参数传递) * [float 与 double](#float-与-double) @@ -64,7 +65,7 @@ int y = x; // 拆箱 new Integer(123) 与 Integer.valueOf(123) 的区别在于: -- new Integer(123) 每次都会新建一个对象 +- new Integer(123) 每次都会新建一个对象; - Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。 ```java @@ -193,33 +194,90 @@ String 不可变性天生具备线程安全,可以在多个线程中安全地 [StackOverflow : String, StringBuffer, and StringBuilder](https://stackoverflow.com/questions/2971315/string-stringbuffer-and-stringbuilder) -## String.intern() +## String Pool -使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象。 +字符串常量池(String Poll)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Poll 中。 -下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同对象,而 s3 是通过 s1.intern() 方法取得一个对象引用。intern() 首先把 s1 引用的对象放到 String Pool(字符串常量池)中,然后返回这个对象引用。因此 s3 和 s1 引用的是同一个字符串常量池的对象。 +当一个字符串调用 intern() 方法时,如果 String Poll 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Poll 中字符串的引用;否则,就会在 String Poll 中添加一个新的字符串,并返回这个新字符串的引用。 + +下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。 ```java String s1 = new String("aaa"); String s2 = new String("aaa"); System.out.println(s1 == s2); // false String s3 = s1.intern(); -System.out.println(s1.intern() == s3); // true +String s4 = s1.intern(); +System.out.println(s3 == s4); // true ``` -如果是采用 "bbb" 这种使用双引号的形式创建字符串实例,会自动地将新建的对象放入 String Pool 中。 +如果是采用 "bbb" 这种字面量的形式创建字符串,会自动地将字符串放入 String Pool 中。 ```java -String s4 = "bbb"; String s5 = "bbb"; +String s6 = "bbb"; System.out.println(s4 == s5); // true ``` -在 Java 7 之前,字符串常量池被放在运行时常量池中,它属于永久代。而在 Java 7,字符串常量池被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 +在 Java 7 之前,String Poll 被放在运行时常量池中,它属于永久代。而在 Java 7,String Poll 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 - [StackOverflow : What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning) - [深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html) +## new String("abc") + +使用这种方式一共会创建两个字符串对象(前提是 String Poll 中还没有 "abc" 字符串对象)。 + +- "abc" 属于字符串字面量,因此编译时期会在 String Poll 中创建一个字符串对象,指向这个 "abc" 字符串字面量; +- 而使用 new 的方式会在堆中创建一个字符串对象。 + +创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。 + +```java +public class NewStringTest { + public static void main(String[] args) { + String s = new String("abc"); + } +} +``` + +使用 javap -verbose 进行反编译,得到以下内容: + +```java +// ... +Constant pool: +// ... + #2 = Class #18 // java/lang/String + #3 = String #19 // abc +// ... + #18 = Utf8 java/lang/String + #19 = Utf8 abc +// ... + + public static void main(java.lang.String[]); + descriptor: ([Ljava/lang/String;)V + flags: ACC_PUBLIC, ACC_STATIC + Code: + stack=3, locals=2, args_size=1 + 0: new #2 // class java/lang/String + 3: dup + 4: ldc #3 // String abc + 6: invokespecial #4 // Method java/lang/String."":(Ljava/lang/String;)V + 9: astore_1 +// ... +``` + +在 Constant Poll 中,#19 存储这字符串字面量 "abc",#3 是 String Poll 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Poll 中的字符串对象作为 String 构造函数的参数。 + +以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。 + +```java +public String(String original) { + this.value = original.value; + this.hash = original.hash; +} +``` + # 三、运算 ## 参数传递 From 9e987425855fa2f150754ba15d242157f720c3a4 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 26 Aug 2018 23:17:04 +0800 Subject: [PATCH 028/136] auto commit --- notes/Java 基础.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 95249103..5b689cf8 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -461,6 +461,7 @@ public class AccessExample { ```java public class AccessWithInnerClassExample { + private class InnerClass { int x; } @@ -526,6 +527,7 @@ ac2.func1(); ```java public interface InterfaceExample { + void func1(); default void func2(){ @@ -577,7 +579,7 @@ System.out.println(InterfaceExample.x); - 需要能控制继承来的成员的访问权限,而不是都为 public。 - 需要继承非静态和非常量字段。 -在很多情况下,接口优先于抽象类,因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。 +在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。 - [深入理解 abstract class 和 interface](https://www.ibm.com/developerworks/cn/java/l-javainterface-abstract/) - [When to Use Abstract Class and Interface](https://dzone.com/articles/when-to-use-abstract-class-and-intreface) @@ -718,7 +720,7 @@ x.equals(y) == x.equals(y); // true x.equals(null); // false; ``` -**2. equals() 与 ==** +**2. 等价与相等** - 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。 - 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。 @@ -781,7 +783,7 @@ set.add(e2); System.out.println(set.size()); // 2 ``` -理想的散列函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来,可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。 +理想的散列函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来。可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。 一个数与 31 相乘可以转换成移位和减法:`31*x == (x<<5)-x`,编译器会自动进行这个优化。 @@ -886,6 +888,7 @@ public class CloneExample implements Cloneable { ```java public class ShallowCloneExample implements Cloneable { + private int[] arr; public ShallowCloneExample() { @@ -928,6 +931,7 @@ System.out.println(e2.get(2)); // 222 ```java public class DeepCloneExample implements Cloneable { + private int[] arr; public DeepCloneExample() { @@ -975,6 +979,7 @@ System.out.println(e2.get(2)); // 2 ```java public class CloneConstructorExample { + private int[] arr; public CloneConstructorExample() { @@ -1040,7 +1045,7 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 **1. 静态变量** -- 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。 +- 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。 - 实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。 ```java @@ -1059,7 +1064,7 @@ public class A { **2. 静态方法** -静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。 +静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。 ```java public abstract class A { @@ -1182,7 +1187,7 @@ public InitialOrderTest() { 每个类都有一个 **Class** 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。 -类加载相当于 Class 对象的加载。类在第一次使用时才动态加载到 JVM 中,可以使用 `Class.forName("com.mysql.jdbc.Driver")` 这种方式来控制类的加载,该方法会返回一个 Class 对象。 +类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用 `Class.forName("com.mysql.jdbc.Driver")` 这种方式来控制类的加载,该方法会返回一个 Class 对象。 反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。 @@ -1279,7 +1284,7 @@ Java 注解是附加在代码中的一些元信息,用于一些工具在编译 - Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。 - Java 支持自动垃圾回收,而 C++ 需要手动回收。 - Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。 -- Java 不支持操作符重载,虽然可以对两个 String 对象支持加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。 +- Java 不支持操作符重载,虽然可以对两个 String 对象执行加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。 - Java 的 goto 是保留字,但是不可用,C++ 可以使用 goto。 - Java 不支持条件编译,C++ 通过 #ifdef #ifndef 等预处理命令从而实现条件编译。 From 60e2aa5551b685ba0f9493cf92bbf46229298240 Mon Sep 17 00:00:00 2001 From: ziyitony <602232939@qq.com> Date: Sun, 26 Aug 2018 23:52:20 +0800 Subject: [PATCH 029/136] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E7=A9=BA?= =?UTF-8?q?=E5=88=86=E5=A4=8D=E7=94=A8=E6=8A=80=E6=9C=AF=E7=9A=84=E4=BE=8B?= =?UTF-8?q?=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.3 小节增加了虚拟内存作为空分复用的例子 --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 6bfb559c..5c6596b2 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -58,7 +58,7 @@ 虚拟技术把一个物理实体转换为多个逻辑实体。 -主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。 +主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个线程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个线程工作时使用物理内存,线程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 ### 4. 异步 From 3dfc0c7cd8f72b44b238a8a91c7e5dfc92a32622 Mon Sep 17 00:00:00 2001 From: ziyitony <602232939@qq.com> Date: Mon, 27 Aug 2018 00:00:01 +0800 Subject: [PATCH 030/136] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 5c6596b2..0be09349 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -58,7 +58,7 @@ 虚拟技术把一个物理实体转换为多个逻辑实体。 -主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个线程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个线程工作时使用物理内存,线程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 +主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个进程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个进程工作时使用物理内存,进程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 ### 4. 异步 From 4e4c0c2da14680f69d4b28aa07899606980cd580 Mon Sep 17 00:00:00 2001 From: ziyitony <602232939@qq.com> Date: Mon, 27 Aug 2018 00:00:14 +0800 Subject: [PATCH 031/136] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 5c6596b2..0be09349 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -58,7 +58,7 @@ 虚拟技术把一个物理实体转换为多个逻辑实体。 -主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个线程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个线程工作时使用物理内存,线程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 +主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个进程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个进程工作时使用物理内存,进程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 ### 4. 异步 From 785f48ba52e2427456a8c419c9aeeaa5b3699aca Mon Sep 17 00:00:00 2001 From: YiliaZhang <532104074@qq.com> Date: Mon, 27 Aug 2018 23:21:40 +0800 Subject: [PATCH 032/136] =?UTF-8?q?Update=20=E5=89=91=E6=8C=87=20offer=20?= =?UTF-8?q?=E9=A2=98=E8=A7=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5. 替换空格 在for (int i = 0; i < str.length( ); i++)中,str还在一直append,for循环出不去,最终会报OOM --- notes/剑指 offer 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index d88b6168..1162fa71 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -230,7 +230,7 @@ Output: ```java public String replaceSpace(StringBuffer str) { int P1 = str.length() - 1; - for (int i = 0; i < str.length(); i++) + for (int i = 0; i < P1+1; i++) if (str.charAt(i) == ' ') str.append(" "); From 0fd224b3ab2b241cb3d4795a162cb99eac1242e9 Mon Sep 17 00:00:00 2001 From: MasterSJ <452857582@qq.com> Date: Tue, 28 Aug 2018 13:31:55 +0800 Subject: [PATCH 033/136] =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E4=B8=AD=E6=9F=A5?= =?UTF-8?q?=E6=89=BE=E7=9A=84=E7=A9=BA=E6=A0=BC=EF=BC=8C=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E7=9A=84=E4=B9=9F=E6=98=AF=E7=A9=BA=E6=A0=BC?= =?UTF-8?q?=E5=B0=B1=E6=AD=BB=E5=BE=AA=E7=8E=AF=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/剑指 offer 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index d88b6168..43990090 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -232,7 +232,7 @@ public String replaceSpace(StringBuffer str) { int P1 = str.length() - 1; for (int i = 0; i < str.length(); i++) if (str.charAt(i) == ' ') - str.append(" "); + str.append("aa"); int P2 = str.length() - 1; while (P1 >= 0 && P2 > P1) { From 46f19d913c5e9c54e98a80e0ed805c30f7eb9513 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 28 Aug 2018 21:52:21 +0800 Subject: [PATCH 034/136] auto commit --- notes/Java IO.md | 14 +++++++------- notes/MySQL.md | 10 +++++----- notes/Redis.md | 9 ++++----- notes/Socket.md | 14 +++++++------- notes/剑指 offer 题解.md | 4 ++-- notes/计算机操作系统.md | 3 +-- notes/计算机网络.md | 26 ++++++++++++-------------- 7 files changed, 38 insertions(+), 42 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index a14ea902..ee23a4bb 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -6,7 +6,7 @@ * [装饰者模式](#装饰者模式) * [四、字符操作](#四字符操作) * [编码与解码](#编码与解码) - * [String](#string) + * [String 的编码方式](#string-的编码方式) * [Reader 与 Writer](#reader-与-writer) * [实现逐行输出文本文件的内容](#实现逐行输出文本文件的内容) * [五、对象操作](#五对象操作) @@ -121,7 +121,7 @@ UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF- Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。 -## String +## String 的编码方式 String 可以看成一个字符序列,可以指定一个编码方式将它编码为字节序列,也可以指定一个编码方式将一个字节序列解码为 String。 @@ -371,7 +371,7 @@ public static void fastCopy(String src, String dist) throws IOException { /* 获取目标文件的输出字节流 */ FileOutputStream fout = new FileOutputStream(dist); - /* 获取输出字节流的通道 */ + /* 获取输出字节流的文件通道 */ FileChannel fcout = fout.getChannel(); /* 为缓冲区分配 1024 个字节 */ @@ -392,7 +392,7 @@ public static void fastCopy(String src, String dist) throws IOException { /* 把缓冲区的内容写入输出文件中 */ fcout.write(buffer); - + /* 清空缓冲区 */ buffer.clear(); } @@ -407,7 +407,7 @@ NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用 通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。 -因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件具有更好的性能。 +因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件,对于 IO 密集型的应用具有很好地性能。 应该注意的是,只有套接字 Channel 才能配置为非阻塞,而 FileChannel 不能,为 FileChannel 配置非阻塞也没有意义。 @@ -601,8 +601,8 @@ MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024); NIO 与普通 I/O 的区别主要有以下两点: -- NIO 是非阻塞的 -- NIO 面向块,I/O 面向流 +- NIO 是非阻塞的; +- NIO 面向块,I/O 面向流。 # 八、参考资料 diff --git a/notes/MySQL.md b/notes/MySQL.md index bf795d34..f115ce92 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -48,7 +48,7 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具 进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。 -插入删除操作记录会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。 +插入删除操作会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。 ### 3. 与红黑树的比较 @@ -233,7 +233,7 @@ do { ### 2. 分解大连接查询 -将一个大连接查询分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有: +将一个大连接查询分解成对每一个表进行一次单表查询,然后在应用程序中进行关联,这样做的好处有: - 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。 - 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。 @@ -332,7 +332,7 @@ MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。 ### 2. TIMESTAMP -和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。 +和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年到 2038 年。 它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。 @@ -372,9 +372,9 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 使用分布式事务来解决,比如 XA 接口。 -### 2. 链接 +### 2. JOIN -可以将原来的 JOIN 分解成多个单表查询,然后在用户程序中进行 JOIN。 +可以将原来的 JOIN 分解成多个单表 JOIN 查询,然后在用户程序中进行 JOIN。 ### 3. ID 唯一性 diff --git a/notes/Redis.md b/notes/Redis.md index 629fcdd8..58320dfa 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -49,7 +49,7 @@ Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 -键的类型只能为字符串,值支持的五种类型数据类型为:字符串、列表、集合、散列表、有序集合。 +键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。 @@ -58,7 +58,7 @@ Redis 支持很多特性,例如将内存中的数据持久化到硬盘中, | 数据类型 | 可以存储的值 | 操作 | | :--: | :--: | :--: | | STRING | 字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作
对整数和浮点数执行自增或者自减操作 | -| LIST | 列表 | 从两端压入或者弹出元素
对单个或者多个元素
进行修剪,只保留一个范围内的元素 | +| LIST | 列表 | 从两端压入或者弹出元素
对单个或者多个元素
进行修剪,只保留一个范围内的元素 | | SET | 无序集合 | 添加、获取、移除单个元素
检查一个元素是否存在于集合中
计算交集、并集、差集
从集合里面随机获取元素 | | HASH | 包含键值对的无序散列表 | 添加、获取、移除单个键值对
获取所有键值对
检查某个键是否存在| | ZSET | 有序集合 | 添加、获取、删除元素
根据分值范围或者成员来获取元素
计算一个键的排名 | @@ -357,7 +357,7 @@ List 是一个双向链表,可以通过 lpop 和 lpush 写入和读取消息 在分布式场景下具有多个应用服务器,可以使用 Redis 来统一存储这些应用服务器的会话信息。 -当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器。 +当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。 ## 分布式锁实现 @@ -393,7 +393,7 @@ Redis Cluster 实现了分布式的支持。 - 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘,而 Memcached 的数据则会一直在内存中。 -- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题,但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。 +- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。 # 六、键的过期时间 @@ -605,5 +605,4 @@ Redis 没有关系型数据库中的表这一概念来将同种类型的数据 - [论述 Redis 和 Memcached 的差异](http://www.cnblogs.com/loveincode/p/7411911.html) - [Redis 3.0 中文版- 分片](http://wiki.jikexueyuan.com/project/redis-guide) - [Redis 应用场景](http://www.scienjus.com/redis-use-case/) -- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/) - [Using Redis as an LRU cache](https://redis.io/topics/lru-cache) diff --git a/notes/Socket.md b/notes/Socket.md index 8e7c0b89..482bafe6 100644 --- a/notes/Socket.md +++ b/notes/Socket.md @@ -25,9 +25,9 @@ - 等待数据准备好 - 从内核向进程复制数据 -对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。 +对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待数据到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。 -Unix 下有五种 I/O 模型: +Unix 有五种 I/O 模型: - 阻塞式 I/O - 非阻塞式 I/O @@ -39,7 +39,7 @@ Unix 下有五种 I/O 模型: 应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。 -应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的执行效率会比较高。 +应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。 下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。 @@ -53,13 +53,13 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * 应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。 -由于 CPU 要处理更多的系统调用,因此这种模型是比较低效的。 +由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率是比较低的。

## I/O 复用 -使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读,这一过程会被阻塞,当某一个套接字可读时返回。之后再使用 recvfrom 把数据从内核复制到进程中。 +使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。 它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。 @@ -77,7 +77,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * ## 异步 I/O -进行 aio_read 系统调用会立即返回,应用进程继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。 +应用进程执行 aio_read 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。 异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。 @@ -198,7 +198,7 @@ else select 和 poll 的功能基本相同,不过在一些实现细节上有所不同。 - select 会修改描述符,而 poll 不会; -- select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用链表实现,没有描述符的数量的限制; +- select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用链表实现,没有描述符数量的限制; - poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。 - 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 83f03d8e..63cf170e 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -230,9 +230,9 @@ Output: ```java public String replaceSpace(StringBuffer str) { int P1 = str.length() - 1; - for (int i = 0; i < P1+1; i++) + for (int i = 0; i < P1 + 1; i++) if (str.charAt(i) == ' ') - str.append("aa"); + str.append(" "); int P2 = str.length() - 1; while (P1 >= 0 && P2 > P1) { diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 6bfb559c..b3b0a41b 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -791,12 +791,11 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问

- ### 6. 时钟 > Clock -第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面链接起来,再使用一个指针指向最老的页面。 +第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。

diff --git a/notes/计算机网络.md b/notes/计算机网络.md index e80ba7f8..99a6fb43 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -59,7 +59,7 @@ 网络把主机连接起来,而互联网是把多种不同的网络连接起来,因此互联网是网络的网络。 -

+

## ISP @@ -67,9 +67,7 @@

-目前的互联网是一种多层次 ISP 结构,ISP 根据覆盖面积的大小分为第一层 ISP、区域 ISP 和接入 ISP。 - -互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP。 +目前的互联网是一种多层次 ISP 结构,ISP 根据覆盖面积的大小分为第一层 ISP、区域 ISP 和接入 ISP。互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP。

@@ -125,7 +123,7 @@ ## 计算机网络体系结构* -

+

### 1. 五层协议 @@ -143,7 +141,7 @@ 其中表示层和会话层用途如下: -- **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必担心在各台主机中数据内部格式不同的问题。 +- **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。 - **会话层** :建立及管理会话。 @@ -700,7 +698,7 @@ TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文

-TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。 +TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。 发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。 @@ -713,11 +711,11 @@ TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、 ### 1. 慢开始与拥塞避免 -发送的最初执行慢开始,令 cwnd=1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 ... +发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 ... -注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。 +注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。 -如果出现了超时,则令 ssthresh = cwnd/2,然后重新执行慢开始。 +如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。 ### 2. 快重传与快恢复 @@ -725,7 +723,7 @@ TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、 在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。 -在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd/2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。 +在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。 慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。 @@ -743,8 +741,8 @@ DNS 是一个分布式数据库,提供了主机名和 IP 地址之间相互转 DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53。大多数情况下 DNS 使用 UDP 进行传输,这就要求域名解析器和域名服务器都必须自己处理超时和重传来保证可靠性。在两种情况下会使用 TCP 进行传输: -- 如果返回的响应超过的 512 字节就改用 TCP 进行传输(UDP 最大只支持 512 字节的数据)。 -- 区域传送需要使用 TCP 进行传输(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。 +- 如果返回的响应超过的 512 字节(UDP 最大只支持 512 字节的数据)。 +- 区域传送(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。 ## 文件传送协议 @@ -806,7 +804,7 @@ POP3 的特点是只要用户从服务器上读取了邮件,就把该邮件删 ### 3. IMAP -IMAP 协议中客户端和服务器上的邮件保持同步,如果不去手动删除邮件,那么服务器上的邮件也不会被删除。IMAP 这种做法可以让用户随时随地去访问服务器上的邮件。 +IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删除邮件,那么服务器上的邮件也不会被删除。IMAP 这种做法可以让用户随时随地去访问服务器上的邮件。 ## 常用端口 From 03bb846a22ab22acd608af2e27d0063c44ae1a7a Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 28 Aug 2018 22:02:30 +0800 Subject: [PATCH 035/136] auto commit --- notes/Java 容器.md | 2 +- notes/计算机操作系统.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 57e5f475..fd1ee97e 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -1182,7 +1182,7 @@ ListIterator <-- List - Eckel B. Java 编程思想 [M]. 机械工业出版社, 2002. - [Java Collection Framework](https://www.w3resource.com/java-tutorial/java-collections.php) - [Iterator 模式](https://openhome.cc/Gossip/DesignPattern/IteratorPattern.htm) -- [Java 8 系列之重新认识 HashMap](https://tech.meituan.com/java-hashmap.html) +- [Java 8 系列之重新认识 HashMap](https://tech.meituan.com/java_hashmap.html) - [What is difference between HashMap and Hashtable in Java?](http://javarevisited.blogspot.hk/2010/10/difference-between-hashmap-and.html) - [Java 集合之 HashMap](http://www.zhangchangle.com/2018/02/07/Java%E9%9B%86%E5%90%88%E4%B9%8BHashMap/) - [The principle of ConcurrentHashMap analysis](http://www.programering.com/a/MDO3QDNwATM.html) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4154cf66..73f67c62 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -58,7 +58,11 @@ 虚拟技术把一个物理实体转换为多个逻辑实体。 -主要有两种虚拟技术:时分复用技术和空分复用技术。例如多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。例如多个进程占用的总内存可以超过电脑实际安装的物理内存,但是采用虚拟内存 swap 和页面调度等技术,让每个进程工作时使用物理内存,进程切换的时候将内存内容写入到虚拟内存保存,通过工作在物理内存保存在虚拟内存的方式实现空分复用技术。 +主要有两种虚拟技术:时分复用技术和空分复用技术。 + +多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占有处理器,每次只执行一小个时间片并快速切换。 + +虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间和物理内存使用页进行交换,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。 ### 4. 异步 From 06190f2f1947f4421234ea7912c51fb07d5c79a9 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 28 Aug 2018 22:55:26 +0800 Subject: [PATCH 036/136] auto commit --- notes/算法.md | 78 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/notes/算法.md b/notes/算法.md index a9f9e689..53edc1c1 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -104,17 +104,21 @@ public class ThreeSumSlow implements ThreeSum { public int count(int[] nums) { int N = nums.length; int cnt = 0; - for (int i = 0; i < N; i++) - for (int j = i + 1; j < N; j++) - for (int k = j + 1; k < N; k++) - if (nums[i] + nums[j] + nums[k] == 0) + for (int i = 0; i < N; i++) { + for (int j = i + 1; j < N; j++) { + for (int k = j + 1; k < N; k++) { + if (nums[i] + nums[j] + nums[k] == 0) { cnt++; + } + } + } + } return cnt; } } ``` -### 2. ThreeSumFast +### 2. ThreeSumBinarySearch 通过将数组先排序,对两个元素求和,并用二分查找方法查找是否存在该和的相反数,如果存在,就说明存在三元组的和为 0。 @@ -123,19 +127,23 @@ public class ThreeSumSlow implements ThreeSum { 该方法可以将 ThreeSum 算法增长数量级降低为 O(N2logN)。 ```java -public class ThreeSumFast { - public static int count(int[] nums) { +public class ThreeSumBinarySearch implements ThreeSum { + + @Override + public int count(int[] nums) { Arrays.sort(nums); int N = nums.length; int cnt = 0; - for (int i = 0; i < N; i++) + for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { int target = -nums[i] - nums[j]; int index = BinarySearch.search(nums, target); // 应该注意这里的下标必须大于 j,否则会重复统计。 - if (index > j) + if (index > j) { cnt++; + } } + } return cnt; } } @@ -143,22 +151,59 @@ public class ThreeSumFast { ```java public class BinarySearch { + public static int search(int[] nums, int target) { int l = 0, h = nums.length - 1; while (l <= h) { int m = l + (h - l) / 2; - if (target == nums[m]) + if (target == nums[m]) { return m; - else if (target > nums[m]) + } else if (target > nums[m]) { l = m + 1; - else + } else { h = m - 1; + } } return -1; } } ``` +### 3. ThreeSumTwoPointer + +更有效的方法是先将数组排序,然后使用双指针进行查找,时间复杂度为 O(N2)。 + +```java +public class ThreeSumTwoPointer implements ThreeSum { + + @Override + public int count(int[] nums) { + int N = nums.length; + int cnt = 0; + Arrays.sort(nums); + for (int i = 0; i < N - 2; i++) { + int l = i + 1, h = N - 1, target = -nums[i]; + if (i > 0 && nums[i] == nums[i - 1]) continue; + while (l < h) { + int sum = nums[l] + nums[h]; + if (sum == target) { + cnt++; + while (l < h && nums[l] == nums[l + 1]) l++; + while (l < h && nums[h] == nums[h - 1]) h--; + l++; + h--; + } else if (sum < target) { + l++; + } else { + h--; + } + } + } + return cnt; + } +} +``` + ## 倍率实验 如果 T(N) \~ aNblogN,那么 T(2N)/T(N) \~ 2b。 @@ -180,29 +225,20 @@ public class BinarySearch { public class RatioTest { public static void main(String[] args) { - int N = 500; int loopTimes = 7; double preTime = -1; - while (loopTimes-- > 0) { - int[] nums = new int[N]; - StopWatch.start(); - ThreeSum threeSum = new ThreeSumSlow(); - int cnt = threeSum.count(nums); System.out.println(cnt); - double elapsedTime = StopWatch.elapsedTime(); double ratio = preTime == -1 ? 0 : elapsedTime / preTime; System.out.println(N + " " + elapsedTime + " " + ratio); - preTime = elapsedTime; N *= 2; - } } } From 5426af758eff2c61373154c7b888eab5d70556cd Mon Sep 17 00:00:00 2001 From: Zhiwei Tian Date: Tue, 28 Aug 2018 23:22:13 +0800 Subject: [PATCH 037/136] mistakes --- notes/Java 虚拟机.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 2b565cb5..1a1adc5a 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -268,7 +268,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了 以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。 - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程; -- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并形指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 +- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 ### 1. Serial 收集器 From 58f11f78a85d80a28aac5b6e769027c86b51ea89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Wed, 29 Aug 2018 10:31:07 +0800 Subject: [PATCH 038/136] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 27edaf24..b9f43ec8 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
- +
From 90e46ab379964e38a9e16b8ee08493ff9ede383c Mon Sep 17 00:00:00 2001 From: showCodes <22638002+showCodes@users.noreply.github.com> Date: Thu, 30 Aug 2018 11:02:33 +0800 Subject: [PATCH 039/136] =?UTF-8?q?Update=20Java=20=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E6=9C=BA.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 虚拟机.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 1a1adc5a..40972bfd 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -7,6 +7,8 @@ * [方法区](#方法区) * [运行时常量池](#运行时常量池) * [直接内存](#直接内存) + * [类的创建过程](#类的创建过程) + * [对象的结构](#对象的结构) * [二、垃圾收集](#二垃圾收集) * [判断一个对象是否可被回收](#判断一个对象是否可被回收) * [引用类型](#引用类型) @@ -102,6 +104,28 @@ Class 文件中的常量池(编译器生成的各种字面量和符号引用 这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。 +## 对象的创建过程 + +[图解JAVA对象的创建过程](https://www.cnblogs.com/chenyangyao/p/5296807.html) + +![111](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235423381-1926278401.png) + +## 对象的结构 + +对象包含 3 个部分: +1. Header(对象头):如下图所示; +2. InstanceData(实例数据):将等宽的类型放在一起; +3. Padding(对齐填充):Hotspot 虚拟机的内存管理系统要求对象的起始地址要是 8 个字节的整数倍,而对象头就是 8 个字节的整数倍。padding 是用来填充实例数据不足 8 个字节整数倍的部分,可以理解为占位符。 + +![112](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235633553-1910724119.png) + +## 对象的地址访问 + +1. 直接指针:对象的引用直接指向堆中的内存地址 (Hotspot 采用的方式); +2. 使用句柄:Java 堆中划分出一块内存作为句柄池,对象的引用指向句柄池。 + +![113](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235555303-769658219.jpg) + # 二、垃圾收集 垃圾收集主要是针对堆和方法区进行。 @@ -138,7 +162,7 @@ public class ReferenceCountingGC { Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容: -- 虚拟机栈中引用的对象 +- 虚拟机栈 (局部变量表) 中引用的对象 - 本地方法栈中引用的对象 - 方法区中类静态属性引用的对象 - 方法区中的常量引用的对象 From 3edd3984f48e76a22a95add26f9f29f8b232926b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 30 Aug 2018 20:25:57 +0800 Subject: [PATCH 040/136] auto commit --- notes/Docker.md | 32 +++++++------------- notes/Git.md | 32 ++++++++++---------- notes/HTTP.md | 46 ++++++++++++++-------------- notes/Java 并发.md | 33 ++++++++++---------- notes/Java 虚拟机.md | 30 ++----------------- notes/Linux.md | 10 +++---- notes/分布式.md | 26 ++++++++-------- notes/构建工具.md | 29 +++++++----------- notes/消息队列.md | 2 +- notes/算法.md | 70 +++++++++++++++++++++---------------------- notes/缓存.md | 26 ++++++++-------- notes/计算机网络.md | 6 ++-- notes/设计模式.md | 13 +++++--- notes/重构.md | 6 ++-- notes/集群.md | 6 ++-- notes/面向对象思想.md | 5 +++- 16 files changed, 169 insertions(+), 203 deletions(-) diff --git a/notes/Docker.md b/notes/Docker.md index 80108896..1b61a7fe 100644 --- a/notes/Docker.md +++ b/notes/Docker.md @@ -4,6 +4,7 @@ * [三、优势](#三优势) * [四、使用场景](#四使用场景) * [五、镜像与容器](#五镜像与容器) +* [参考资料](#参考资料) @@ -15,11 +16,6 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 Docker 可以不修改应用程序代码,不需要开发人员学习特定环境下的技术,就能够将现有的应用程序部署在其他机器中。 -参考资料: - -- [DOCKER 101: INTRODUCTION TO DOCKER WEBINAR RECAP](https://blog.docker.com/2017/08/docker-101-introduction-docker-webinar-recap/) -- [Docker 入门教程](http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html) - # 二、与虚拟机的比较 虚拟机也是一种虚拟化技术,它与 Docker 最大的区别在于它是通过模拟硬件,并在硬件上安装操作系统来实现。 @@ -40,30 +36,22 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程 而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 -参考资料: - -- [Docker container vs Virtual machine](http://www.bogotobogo.com/DevOps/Docker/Docker_Container_vs_Virtual_Machine.php) - # 三、优势 除了启动速度快以及占用资源少之外,Docker 具有以下优势: ## 更容易迁移 -Docker 可以提供一致性的运行环境,可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。 +提供一致性的运行环境,可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。 ## 更容易维护 -Docker 使用分层技术和镜像,使得应用可以更容易复用重复部分。复用程度越高,维护工作也越容易。 +使用分层技术和镜像,使得应用可以更容易复用重复部分。复用程度越高,维护工作也越容易。 ## 更容易扩展 可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。 -参考资料: - -- [为什么要使用 Docker?](https://yeasy.gitbooks.io/docker_practice/introduction/why.html) - # 四、使用场景 ## 持续集成 @@ -80,11 +68,6 @@ Docker 具有轻量级以及隔离性的特点,在将代码集成到一个 Doc Docker 轻量级的特点使得它很适合用于部署、维护、组合微服务。 -参考资料: - -- [What is Docker](https://www.docker.com/what-docker) -- [持续集成是什么?](http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html) - # 五、镜像与容器 镜像是一种静态的结构,可以看成面向对象里面的类,而容器是镜像的一个实例。 @@ -95,9 +78,14 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服

-参考资料: +# 参考资料 +- [DOCKER 101: INTRODUCTION TO DOCKER WEBINAR RECAP](https://blog.docker.com/2017/08/docker-101-introduction-docker-webinar-recap/) +- [Docker 入门教程](http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html) +- [Docker container vs Virtual machine](http://www.bogotobogo.com/DevOps/Docker/Docker_Container_vs_Virtual_Machine.php) - [How to Create Docker Container using Dockerfile](https://linoxide.com/linux-how-to/dockerfile-create-docker-container/) - [理解 Docker(2):Docker 镜像](http://www.cnblogs.com/sammyliu/p/5877964.html) - +- [为什么要使用 Docker?](https://yeasy.gitbooks.io/docker_practice/introduction/why.html) +- [What is Docker](https://www.docker.com/what-docker) +- [持续集成是什么?](http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html) diff --git a/notes/Git.md b/notes/Git.md index 4bb0a543..71ff502c 100644 --- a/notes/Git.md +++ b/notes/Git.md @@ -1,8 +1,7 @@ -* [学习资料](#学习资料) * [集中式与分布式](#集中式与分布式) -* [Git 的中心服务器](#git-的中心服务器) -* [Git 工作流](#git-工作流) +* [中心服务器](#中心服务器) +* [工作流](#工作流) * [分支实现](#分支实现) * [冲突](#冲突) * [Fast forward](#fast-forward) @@ -11,16 +10,10 @@ * [SSH 传输设置](#ssh-传输设置) * [.gitignore 文件](#gitignore-文件) * [Git 命令一览](#git-命令一览) +* [参考资料](#参考资料) -# 学习资料 - -- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) -- [图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) -- [廖雪峰 : Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) -- [Learn Git Branching](https://learngitbranching.js.org/) - # 集中式与分布式 Git 属于分布式版本控制系统,而 SVN 属于集中式。 @@ -33,11 +26,13 @@ Git 属于分布式版本控制系统,而 SVN 属于集中式。 分布式版本控制新建分支、合并分支操作速度非常快,而集中式版本控制新建一个分支相当于复制一份完整代码。 -# Git 的中心服务器 +# 中心服务器 -Git 的中心服务器用来交换每个用户的修改。没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。Github 就是一种 Git 中心服务器。 +中心服务器用来交换每个用户的修改,没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。 -# Git 工作流 +Github 就是一个中心服务器。 + +# 工作流

@@ -54,14 +49,14 @@ Git 版本库有一个称为 stage 的暂存区,还有自动创建的 master

-可以跳过暂存区域直接从分支中取出修改或者直接提交修改到分支中 +可以跳过暂存区域直接从分支中取出修改,或者直接提交修改到分支中。 - git commit -a 直接把所有文件的修改添加到暂缓区然后执行提交 - git checkout HEAD -- files 取出最后一次修改,可以用来进行回滚操作 # 分支实现 -Git 把每次提交都连成一条时间线。分支使用指针来实现,例如 master 分支指针指向时间线的最后一个节点,也就是最后一次提交。HEAD 指针指向的是当前分支。 +使用指针将每个提交连接成一条时间线,HEAD 指针指向当前分支指针。

@@ -69,7 +64,7 @@ Git 把每次提交都连成一条时间线。分支使用指针来实现,例

-每次提交只会让当前分支向前移动,而其它分支不会移动。 +每次提交只会让当前分支指针向前移动,而其它分支指针不会移动。

@@ -155,4 +150,9 @@ $ ssh-keygen -t rsa -C "youremail@example.com" 比较详细的地址:http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf +# 参考资料 +- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) +- [图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) +- [廖雪峰 : Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) +- [Learn Git Branching](https://learngitbranching.js.org/) diff --git a/notes/HTTP.md b/notes/HTTP.md index 537b24fe..aae807e6 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -25,6 +25,7 @@ * [实体首部字段](#实体首部字段) * [五、具体应用](#五具体应用) * [Cookie](#cookie) + * [6. Secure](#6-secure) * [缓存](#缓存) * [连接管理](#连接管理) * [内容协商](#内容协商) @@ -310,7 +311,7 @@ HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使 Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。 -Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB。 +Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。 ### 1. 用途 @@ -348,7 +349,17 @@ Cookie: yummy_cookie=choco; tasty_cookie=strawberry Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; ``` -### 4. JavaScript 获取 Cookie +### 4. 作用域 + +Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。 + +Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配: + +- /docs +- /docs/Web/ +- /docs/Web/HTTP + +### 5. JavaScript 通过 `Document.cookie` 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie。 @@ -358,9 +369,7 @@ document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie); ``` -### 5. Secure 和 HttpOnly - -标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 +### 6. HttpOnly 标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 @@ -368,15 +377,9 @@ console.log(document.cookie); Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly ``` -### 6. 作用域 +## 6. Secure -Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。 - -Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配: - -- /docs -- /docs/Web/ -- /docs/Web/HTTP +标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 ### 7. Session @@ -387,8 +390,7 @@ Session 可以存储在服务器上的文件、数据库或者内存中。也可 使用 Session 维护用户登录状态的过程如下: - 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中; -- 服务器验证该用户名和密码; -- 如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID; +- 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID; - 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中; - 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。 @@ -462,13 +464,13 @@ Cache-Control: max-age=31536000 Expires 首部字段也可以用于告知缓存服务器该资源什么时候会过期。 -- 在 HTTP/1.1 中,会优先处理 max-age 指令; -- 在 HTTP/1.0 中,max-age 指令会被忽略掉。 - ```html Expires: Wed, 04 Jul 2012 08:26:05 GMT ``` +- 在 HTTP/1.1 中,会优先处理 max-age 指令; +- 在 HTTP/1.0 中,max-age 指令会被忽略掉。 + ### 4. 缓存验证 需要先了解 ETag 首部字段的含义,它是资源的唯一标识。URL 不能唯一表示资源,例如 `http://www.google.com/` 有中文和英文两个资源,只有 ETag 才能对这两个资源进行唯一标识。 @@ -727,7 +729,7 @@ HTTPs 的报文摘要功能之所以安全,是因为它结合了加密和认 ## HTTP/1.x 缺陷 - HTTP/1.x 实现简单是以牺牲性能为代价的: +HTTP/1.x 实现简单是以牺牲性能为代价的: - 客户端需要使用多个连接才能实现并发和缩短延迟; - 不会压缩请求和响应首部,从而导致不必要的网络流量; @@ -741,9 +743,9 @@ HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式 在通信过程中,只会有一个 TCP 连接存在,它承载了任意数量的双向数据流(Stream)。 -- 一个数据流都有一个唯一标识符和可选的优先级信息,用于承载双向信息。 -- 消息(Message)是与逻辑请求或响应消息对应的完整的一系列帧。 -- 帧(Fram)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。 +- 一个数据流(Stream)都有一个唯一标识符和可选的优先级信息,用于承载双向信息。 +- 消息(Message)是与逻辑请求或响应对应的完整的一系列帧。 +- 帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 1403f764..03aaa9fd 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -637,6 +637,7 @@ B ```java public class WaitNotifyExample { + public synchronized void before() { System.out.println("before"); notifyAll(); @@ -674,12 +675,15 @@ after ## await() signal() signalAll() -java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 +java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。 + +相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 使用 Lock 来获取一个 Condition 对象。 ```java public class AwaitSignalExample { + private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); @@ -809,7 +813,7 @@ before..before..before..before..before..before..before..before..before..before.. ## Semaphore -Semaphore 就是操作系统中的信号量,可以控制对互斥资源的访问线程数。 +Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的访问线程数。

@@ -1098,11 +1102,11 @@ Java 内存模型定义了 8 个操作来完成主内存和工作内存的交互 Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性,例如对一个 int 类型的变量执行 assign 赋值操作,这个操作就是原子性的。但是 Java 内存模型允许虚拟机将没有被 volatile 修饰的 64 位数据(long,double)的读写操作划分为两次 32 位的操作来进行,即 load、store、read 和 write 操作可以不具备原子性。 -有一个错误认识就是,int 等原子性的变量在多线程环境中不会出现线程安全问题。前面的线程不安全示例代码中,cnt 变量属于 int 类型变量,1000 个线程对它进行自增操作之后,得到的值为 997 而不是 1000。 +有一个错误认识就是,int 等原子性的类型在多线程环境中不会出现线程安全问题。前面的线程不安全示例代码中,cnt 属于 int 类型变量,1000 个线程对它进行自增操作之后,得到的值为 997 而不是 1000。 为了方便讨论,将内存间的交互操作简化为 3 个:load、assign、store。 -下图演示了两个线程同时对 cnt 变量进行操作,load、assign、store 这一系列操作整体上看不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入该变量的值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。 +下图演示了两个线程同时对 cnt 进行操作,load、assign、store 这一系列操作整体上看不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入旧值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。

@@ -1200,9 +1204,7 @@ public static void main(String[] args) throws InterruptedException { ### 3. 有序性 -有序性是指:在本线程内观察,所有操作都是有序的。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。 - -在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。 +有序性是指:在本线程内观察,所有操作都是有序的。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。 volatile 关键字通过添加内存屏障的方式来禁止指令重排,即重排序时不能把后面的指令放到内存屏障之前。 @@ -1413,7 +1415,7 @@ synchronized 和 ReentrantLock。 **(二)AtomicInteger** -J.U.C 包里面的整数原子类 AtomicInteger,其中的 compareAndSet() 和 getAndIncrement() 等方法都使用了 Unsafe 类的 CAS 操作。 +J.U.C 包里面的整数原子类 AtomicInteger 的方法调用了 Unsafe 类的 CAS 操作。 以下代码使用了 AtomicInteger 执行了自增的操作。 @@ -1425,7 +1427,7 @@ public void add() { } ``` -以下代码是 incrementAndGet() 的源码,它调用了 unsafe 的 getAndAddInt() 。 +以下代码是 incrementAndGet() 的源码,它调用了 Unsafe 的 getAndAddInt() 。 ```java public final int incrementAndGet() { @@ -1463,9 +1465,6 @@ J.U.C 包提供了一个带有标记的原子引用类 AtomicStampedReference 多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在虚拟机栈中,属于线程私有的。 ```java -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - public class StackClosedExample { public void add100() { int cnt = 0; @@ -1555,7 +1554,7 @@ public class ThreadLocalExample1 {

-每个 Thread 都有一个 ThreadLocal.ThreadLocalMap 对象,Thread 类中就定义了 ThreadLocal.ThreadLocalMap 成员。 +每个 Thread 都有一个 ThreadLocal.ThreadLocalMap 对象。 ```java /* ThreadLocal values pertaining to this thread. This map is maintained @@ -1686,15 +1685,15 @@ JDK 1.6 引入了偏向锁和轻量级锁,从而让锁拥有了四个状态: - 缩小同步范围,从而减少锁争用。例如对于 synchronized,应该尽量使用同步块而不是同步方法。 -- 多用同步工具少用 wait() 和 notify()。首先,CountDownLatch, CyclicBarrier, Semaphore 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现复杂控制流;其次,这些同步类是由最好的企业编写和维护,在后续的 JDK 中还会不断优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。 +- 多用同步工具少用 wait() 和 notify()。首先,CountDownLatch, CyclicBarrier, Semaphore 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现复杂控制流;其次,这些同步类是由最好的企业编写和维护,在后续的 JDK 中还会不断优化和完善。 + +- 使用 BlockingQueue 实现生产者消费者问题。 - 多用并发集合少用同步集合,例如应该使用 ConcurrentHashMap 而不是 Hashtable。 - 使用本地变量和不可变类来保证线程安全。 -- 使用线程池而不是直接创建 Thread 对象,这是因为创建线程代价很高,线程池可以有效地利用有限的线程来启动任务。 - -- 使用 BlockingQueue 实现生产者消费者问题。 +- 使用线程池而不是直接创建线程,这是因为创建线程代价很高,线程池可以有效地利用有限的线程来启动任务。 # 参考资料 diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 40972bfd..1dc4d1d6 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -7,8 +7,6 @@ * [方法区](#方法区) * [运行时常量池](#运行时常量池) * [直接内存](#直接内存) - * [类的创建过程](#类的创建过程) - * [对象的结构](#对象的结构) * [二、垃圾收集](#二垃圾收集) * [判断一个对象是否可被回收](#判断一个对象是否可被回收) * [引用类型](#引用类型) @@ -104,28 +102,6 @@ Class 文件中的常量池(编译器生成的各种字面量和符号引用 这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。 -## 对象的创建过程 - -[图解JAVA对象的创建过程](https://www.cnblogs.com/chenyangyao/p/5296807.html) - -![111](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235423381-1926278401.png) - -## 对象的结构 - -对象包含 3 个部分: -1. Header(对象头):如下图所示; -2. InstanceData(实例数据):将等宽的类型放在一起; -3. Padding(对齐填充):Hotspot 虚拟机的内存管理系统要求对象的起始地址要是 8 个字节的整数倍,而对象头就是 8 个字节的整数倍。padding 是用来填充实例数据不足 8 个字节整数倍的部分,可以理解为占位符。 - -![112](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235633553-1910724119.png) - -## 对象的地址访问 - -1. 直接指针:对象的引用直接指向堆中的内存地址 (Hotspot 采用的方式); -2. 使用句柄:Java 堆中划分出一块内存作为句柄池,对象的引用指向句柄池。 - -![113](https://images2015.cnblogs.com/blog/592743/201603/592743-20160319235555303-769658219.jpg) - # 二、垃圾收集 垃圾收集主要是针对堆和方法区进行。 @@ -162,8 +138,8 @@ public class ReferenceCountingGC { Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容: -- 虚拟机栈 (局部变量表) 中引用的对象 -- 本地方法栈中引用的对象 +- 虚拟机栈中局部变量表中引用的对象 +- 本地方法栈中 JNI 中引用的对象 - 方法区中类静态属性引用的对象 - 方法区中的常量引用的对象 @@ -292,7 +268,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了 以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。 - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程; -- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 +- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并形指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 ### 1. Serial 收集器 diff --git a/notes/Linux.md b/notes/Linux.md index 73a2e9ec..4ba647a7 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -644,7 +644,7 @@ locate 使用 /var/lib/mlocate/ 这个数据库来进行搜索,它存储在内 example: find . -name "shadow*" ``` -(一)与时间有关的选项 +**① 与时间有关的选项** ```html -mtime n :列出在 n 天前的那一天修改过内容的文件 @@ -657,7 +657,7 @@ example: find . -name "shadow*"

-(二)与文件拥有者和所属群组有关的选项 +**② 与文件拥有者和所属群组有关的选项** ```html -uid n @@ -668,7 +668,7 @@ example: find . -name "shadow*" -nogroup:搜索所属群组不存在于 /etc/group 的文件 ``` -(三)与文件权限和名称有关的选项 +**③ 与文件权限和名称有关的选项** ```html -name filename @@ -1038,9 +1038,7 @@ $ grep -n 'go\{2,5\}g' regular_express.txt ## printf -用于格式化输出。 - -它不属于管道命令,在给 printf 传数据时需要使用 $( ) 形式。 +用于格式化输出。它不属于管道命令,在给 printf 传数据时需要使用 $( ) 形式。 ```html $ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt) diff --git a/notes/分布式.md b/notes/分布式.md index e98f2860..113837ce 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -29,18 +29,18 @@ # 一、分布式锁 -在单机场景下,可以使用 Java 提供的内置锁来实现进程同步。但是在分布式场景下,需要同步的进程可能位于不同的节点上,那么就需要使用分布式锁。 +在单机场景下,可以使用语言的内置锁来实现进程同步。但是在分布式场景下,需要同步的进程可能位于不同的节点上,那么就需要使用分布式锁。 阻塞锁通常使用互斥量来实现: -- 互斥量为 1 表示有其它进程在使用锁,此时处于锁定状态; -- 互斥量为 0 表示未锁定状态。 +- 互斥量为 0 表示有其它进程在使用锁,此时处于锁定状态; +- 互斥量为 1 表示未锁定状态。 -1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示,存在表示互斥量为 1。 +1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示。 ## 数据库的唯一索引 -当想要获得锁时,就向表中插入一条记录,释放锁时就删除这条记录。唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否存于锁定状态。 +获得锁时向表中插入一条记录,释放锁时删除这条记录。唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否存于锁定状态。 存在以下几个问题: @@ -91,11 +91,11 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ### 5. 会话超时 -如果一个已经获得锁的会话超时了,因为创建的是临时节点,所以该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库的唯一索引实现分布式锁的释放锁失败问题。 +如果一个已经获得锁的会话超时了,因为创建的是临时节点,所以该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库的唯一索引实现的分布式锁释放锁失败问题。 ### 6. 羊群效应 -一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 +一个节点未获得锁,只需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 # 二、分布式事务 @@ -159,9 +159,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ## 一致性 -一致性指的是多个数据副本是否能保持一致的特性。 - -在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。 +一致性指的是多个数据副本是否能保持一致的特性,在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。 对系统的一个数据更新成功之后,如果所有用户都能够读取到最新的值,该系统就被认为具有强一致性。 @@ -169,7 +167,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操,请求总是能够在有限的时间内返回结果。 ## 分区容忍性 @@ -179,9 +177,9 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ## 权衡 -在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际在是要在可用性和一致性之间做权衡。 +在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际上是要在可用性和一致性之间做权衡。 -可用性和一致性往往是冲突的,很难都使它们同时满足。在多个节点之间进行数据同步时, +可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时, - 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; - 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。 @@ -204,7 +202,7 @@ BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思 ## 软状态 -指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在延时。 +指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在时延。 ## 最终一致性 diff --git a/notes/构建工具.md b/notes/构建工具.md index ce157934..34fef54b 100644 --- a/notes/构建工具.md +++ b/notes/构建工具.md @@ -1,11 +1,12 @@ -* [一、什么是构建工具](#一什么是构建工具) +* [一、构建工具的作用](#一构建工具的作用) * [二、Java 主流构建工具](#二java-主流构建工具) * [三、Maven](#三maven) +* [参考资料](#参考资料) -# 一、什么是构建工具 +# 一、构建工具的作用 构建工具是用于构建项目的自动化工具,主要包含以下工作: @@ -29,10 +30,6 @@ 不再需要通过 FTP 将 Jar 包上传到服务器上。 -参考资料: - -- [What is a build tool?](https://stackoverflow.com/questions/7249871/what-is-a-build-tool) - # 二、Java 主流构建工具 主要包括 Ant、Maven 和 Gradle。 @@ -72,12 +69,6 @@ dependencies { } ``` -参考资料: - -- [Java Build Tools Comparisons: Ant vs Maven vs Gradle](https://programmingmitra.blogspot.com/2016/05/java-build-tools-comparisons-ant-vs.html) -- [maven 2 gradle](http://sagioto.github.io/maven2gradle/) -- [新一代构建工具 gradle](https://www.imooc.com/learn/833) - # 三、Maven ## 概述 @@ -114,7 +105,7 @@ POM 代表项目对象模型,它是一个 XML 文件,保存在项目根目 ## 依赖原则 -### 依赖路径最短优先原则 +### 1. 依赖路径最短优先原则 ```html A -> B -> C -> X(1.0) @@ -122,7 +113,7 @@ A -> D -> X(2.0) ``` 由于 X(2.0) 路径最短,所以使用 X(2.0)。 -### 声明顺序优先原则 +### 2. 声明顺序优先原则 ```html A -> B -> X(1.0) @@ -131,7 +122,7 @@ A -> C -> X(2.0) 在 POM 中最先声明的优先,上面的两个依赖如果先声明 B,那么最后使用 X(1.0)。 -### 覆写优先原则 +### 3. 覆写优先原则 子 POM 内声明的依赖优先于父 POM 中声明的依赖。 @@ -139,9 +130,11 @@ A -> C -> X(2.0) 找到 Maven 加载的 Jar 包版本,使用 `mvn dependency:tree` 查看依赖树,根据依赖原则来调整依赖在 POM 文件的声明顺序。 -参考资料: +# 参考资料 - [POM Reference](http://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification) - - +- [What is a build tool?](https://stackoverflow.com/questions/7249871/what-is-a-build-tool) +- [Java Build Tools Comparisons: Ant vs Maven vs Gradle](https://programmingmitra.blogspot.com/2016/05/java-build-tools-comparisons-ant-vs.html) +- [maven 2 gradle](http://sagioto.github.io/maven2gradle/) +- [新一代构建工具 gradle](https://www.imooc.com/learn/833) diff --git a/notes/消息队列.md b/notes/消息队列.md index 209d962a..bc80894d 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -40,7 +40,7 @@ 发送者将消息发送给消息队列之后,不需要同步等待消息接收者处理完毕,而是立即返回进行其它操作。消息接收者从消息队列中订阅消息之后异步处理。 -例如在注册流程中通常需要发送验证邮件来确保注册用户的身份合法,可以使用消息队列使发送验证邮件的操作异步处理,用户在填写完注册信息之后就可以完成注册,而将发送验证邮件这一消息发送到消息队列中。 +例如在注册流程中通常需要发送验证邮件来确保注册用户身份的合法性,可以使用消息队列使发送验证邮件的操作异步处理,用户在填写完注册信息之后就可以完成注册,而将发送验证邮件这一消息发送到消息队列中。 只有在业务流程允许异步处理的情况下才能这么做,例如上面的注册流程中,如果要求用户对验证邮件进行点击之后才能完成注册的话,就不能再使用消息队列。 diff --git a/notes/算法.md b/notes/算法.md index 53edc1c1..cb83830b 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -379,7 +379,7 @@ public class Insertion> extends Sort { 对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。 -希尔排序的出现就是为了改进插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 +希尔排序的出现就是为了解决插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。 @@ -571,15 +571,15 @@ private int partition(T[] nums, int l, int h) { ### 4. 算法改进 -(一)切换到插入排序 +#### 4.1 切换到插入排序 因为快速排序在小数组中也会递归调用自己,对于小数组,插入排序比快速排序的性能更好,因此在小数组中可以切换到插入排序。 -(二)三数取中 +#### 4.2 三数取中 最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。人们发现取 3 个元素并将大小居中的元素作为切分元素的效果最好。 -(三)三向切分 +#### 4.3 三向切分 对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。 @@ -645,7 +645,7 @@ public T select(T[] nums, int k) { 堆的某个节点的值总是大于等于子节点的值,并且堆是一颗完全二叉树。 -堆可以用数组来表示,因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。 +堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。

@@ -739,15 +739,15 @@ public T delMax() { ### 5. 堆排序 -由于堆可以很容易得到最大的元素并删除它,不断地进行这种操作可以得到一个递减序列。如果把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列。因此很容易使用堆来进行排序。并且堆排序是原地排序,不占用额外空间。 +把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列,这就是堆排序。 -(一)构建堆 +#### 5.1 构建堆 -无序数组建立堆最直接的方法是从左到右遍历数组,然后进行上浮操作。一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。 +无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作。一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。

-(二)交换堆顶元素与最后一个元素 +#### 5.2 交换堆顶元素与最后一个元素 交换之后需要进行下沉操作维持堆的有序状态。 @@ -804,7 +804,7 @@ public class HeapSort> extends Sort { ### 1. 排序算法的比较 -| 算法 | 稳定 | 时间复杂度 | 空间复杂度 | 备注 | +| 算法 | 稳定性 | 时间复杂度 | 空间复杂度 | 备注 | | :---: | :---: |:---: | :---: | :---: | | 选择排序 | × | N2 | 1 | | | 冒泡排序 | √ | N2 | 1 | | @@ -815,7 +815,7 @@ public class HeapSort> extends Sort { | 归并排序 | √ | NlogN | N | | | 堆排序 | × | NlogN | 1 | | | -快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN,这里的 c 比其他线性对数级别的排序算法都要小。使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。 +快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN,这里的 c 比其它线性对数级别的排序算法都要小。使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。 ### 2. Java 的排序算法实现 @@ -882,7 +882,6 @@ public class QuickFindUF extends UF { @Override public void union(int p, int q) { - int pID = find(p); int qID = find(q); @@ -917,7 +916,6 @@ public class QuickUnionUF extends UF { @Override public int find(int p) { - while (p != id[p]) { p = id[p]; } @@ -927,7 +925,6 @@ public class QuickUnionUF extends UF { @Override public void union(int p, int q) { - int pRoot = find(p); int qRoot = find(q); @@ -938,7 +935,7 @@ public class QuickUnionUF extends UF { } ``` -这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为触点的数目。 +这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为节点的数目。

@@ -1588,7 +1585,7 @@ public class BST, Value> implements OrderedST

@@ -1806,9 +1803,9 @@ private List keys(Node x, Key l, Key h) { } ``` -### 10. 性能分析 +### 10. 分析 -复杂度:二叉查找树所有操作在最坏的情况下所需要的时间都和树的高度成正比。 +二叉查找树所有操作在最坏的情况下所需要的时间都和树的高度成正比。 ## 2-3 查找树 @@ -1838,7 +1835,7 @@ private List keys(Node x, Key l, Key h) { ## 红黑树 -2-3 查找树需要用到 2- 节点和 3- 节点,红黑树使用红链接来实现 3- 节点。指向一个节点的链接颜色如果为红色,那么这个节点和上层节点表示的是一个 3- 节点,而黑色则是普通链接。 +红黑树是 2-3 查找树,但它不需要分别定义 2- 节点和 3- 节点,而是在普通的二叉查找树之上,为节点添加颜色。指向一个节点的链接颜色如果为红色,那么这个节点和上层节点表示的是一个 3- 节点,而黑色则是普通链接。

@@ -1853,6 +1850,7 @@ private List keys(Node x, Key l, Key h) { ```java public class RedBlackBST, Value> extends BST { + private static final boolean RED = true; private static final boolean BLACK = false; @@ -2008,16 +2006,17 @@ int hash = (((day * R + month) % M) * R + year) % M; R 通常取 31。 -Java 中的 hashCode() 实现了 hash 函数,但是默认使用对象的内存地址值。在使用 hashCode() 函数时,应当结合除留余数法来使用。因为内存地址是 32 位整数,我们只需要 31 位的非负整数,因此应当屏蔽符号位之后再使用除留余数法。 +Java 中的 hashCode() 实现了哈希函数,但是默认使用对象的内存地址值。在使用 hashCode() 时,应当结合除留余数法来使用。因为内存地址是 32 位整数,我们只需要 31 位的非负整数,因此应当屏蔽符号位之后再使用除留余数法。 ```java int hash = (x.hashCode() & 0x7fffffff) % M; ``` -使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode(): +使用 Java 的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode(): ```java public class Transaction { + private final String who; private final Date when; private final double amount; @@ -2039,17 +2038,17 @@ public class Transaction { } ``` -### 2. 基于拉链法的散列表 +### 2. 拉链法 拉链法使用链表来存储 hash 值相同的键,从而解决冲突。 查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。 -对于 N 个键,M 条链表 (N>M),如果 hash 函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。 +对于 N 个键,M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。

-### 3. 基于线性探测法的散列表 +### 3. 线性探测法 线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。 @@ -2059,6 +2058,7 @@ public class Transaction { ```java public class LinearProbingHashST implements UnorderedST { + private int N = 0; private int M = 16; private Key[] keys; @@ -2084,7 +2084,7 @@ public class LinearProbingHashST implements UnorderedST } ``` -**(一)查找** +#### 3.1 查找 ```java public Value get(Key key) { @@ -2096,7 +2096,7 @@ public Value get(Key key) { } ``` -**(二)插入** +#### 3.2 插入 ```java public void put(Key key, Value value) { @@ -2118,7 +2118,7 @@ private void putInternal(Key key, Value value) { } ``` -**(三)删除** +#### 3.3 删除 删除操作应当将右侧所有相邻的键值对重新插入散列表中。 @@ -2151,7 +2151,7 @@ public void delete(Key key) { } ``` -**(四)调整数组大小** +#### 3.5 调整数组大小 线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。例如下图中 2\~5 位置就是一个聚簇。 @@ -2235,15 +2235,15 @@ public class SparseVector { 这是一个经典的递归问题,分为三步求解: -- 将 n-1 个圆盘从 from -> buffer +① 将 n-1 个圆盘从 from -> buffer

-- 将 1 个圆盘从 from -> to +② 将 1 个圆盘从 from -> to

-- 将 n-1 个圆盘从 buffer -> to +③ 将 n-1 个圆盘从 buffer -> to

@@ -2281,9 +2281,9 @@ from H1 to H3 ## 哈夫曼编码 -哈夫曼编码根据数据出现的频率对数据进行编码,从而压缩原始数据。 +根据数据出现的频率对数据进行编码,从而压缩原始数据。 -例如对于文本文件,其中各种字符出现的次数如下: +例如对于一个文本文件,其中各种字符出现的次数如下: - a : 10 - b : 20 @@ -2294,7 +2294,7 @@ from H1 to H3 首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 -生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到根节点,根节点代表的字符的编码就是这个路径编码。 +生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。

diff --git a/notes/缓存.md b/notes/缓存.md index ed834253..26d96be1 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -26,16 +26,16 @@ ## 淘汰策略 -- FIFO(First In First Out):先进先出策略,在实时性的场景下,需要经常访问最新的数据,那么就可以使用 FIFO,使最先进入的数据(最晚的数据)被淘汰。 +- FIFO(First In First Out):先进先出策略,在实时性的场景下,需要经常访问最新的数据,那么就可以使用 FIFO,使得最先进入的数据(最晚的数据)被淘汰。 -- LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最远的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 +- LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最久的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 # 二、LRU -以下是一个基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: +以下是基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: -- 最基本的思路是当访问某个节点时,将其从原来的位置删除,并重新插入到链表头部,这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就删除链表尾部的节点。 -- 为了使删除操作时间复杂度为 O(1),那么就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。 +- 访问某个节点时,将其从原来的位置删除,并重新插入到链表头部。这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就淘汰链表尾部的节点。 +- 为了使删除操作时间复杂度为 O(1),就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。 ```java public class LRU implements Iterable { @@ -152,7 +152,7 @@ public class LRU implements Iterable { ## 反向代理 -反向代理位于服务器之前,请求与响应都需要经过反向代理。通过将数据缓存在反向代理,在用户请求时就可以直接使用缓存进行响应。 +反向代理位于服务器之前,请求与响应都需要经过反向代理。通过将数据缓存在反向代理,在用户请求反向代理时就可以直接使用缓存进行响应。 ## 本地缓存 @@ -166,7 +166,7 @@ public class LRU implements Iterable { ## 数据库缓存 -MySQL 等数据库管理系统具有自己的查询缓存机制来提高 SQL 查询效率。 +MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率。 # 四、CDN @@ -193,9 +193,9 @@ CDN 主要有以下优点: ## 缓存雪崩 -指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都去到达数据库。 +指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。 -在存在缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。 +在有缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。 解决方案: @@ -233,7 +233,7 @@ CDN 主要有以下优点: # 七、一致性哈希 -Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据失效的问题。 +Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题。 ## 基本原理 @@ -241,7 +241,7 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了

-一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它前一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。 +一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它后一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。

@@ -249,7 +249,9 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了 上面描述的一致性哈希存在数据分布不均匀的问题,节点存储的数据量有可能会存在很大的不同。 -数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得大,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 +数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。 + +解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得多,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 # 参考资料 diff --git a/notes/计算机网络.md b/notes/计算机网络.md index 99a6fb43..e5b8dfcf 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -59,7 +59,7 @@ 网络把主机连接起来,而互联网是把多种不同的网络连接起来,因此互联网是网络的网络。 -

+

## ISP @@ -304,7 +304,7 @@ PPP 的帧格式: MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标识网络适配器(网卡)。 -一台主机拥有多少个适配器就有多少个 MAC 地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器,因此就有两个 MAC 地址。 +一台主机拥有多少个网络适配器就有多少个 MAC 地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器,因此就有两个 MAC 地址。 ## 局域网 @@ -320,7 +320,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标 以太网是一种星型拓扑结构局域网。 -早期使用集线器进行连接,集线器是一种物理层设备,作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到同时从两个不同接口的帧,那么就发生了碰撞。 +早期使用集线器进行连接,集线器是一种物理层设备, 作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到同时从两个不同接口的帧,那么就发生了碰撞。 目前以太网使用交换机替代了集线器,交换机是一种链路层设备,它不会发生碰撞,能根据 MAC 地址进行存储转发。 diff --git a/notes/设计模式.md b/notes/设计模式.md index 531595e3..d7ef735a 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -726,7 +726,12 @@ request2 is handle by ConcreteHandler2 ### 意图 -将命令封装成对象中,以便使用命令来参数化其它对象,或者将命令对象放入队列中进行排队,或者将命令对象的操作记录到日志中,以及支持可撤销的操作。 +将命令封装成对象中,具有以下作用: + +- 使用命令来参数化其它对象 +- 将命令放入队列中进行排队 +- 将命令的操作记录到日志中 +- 支持可撤销的操作 ### 类图 @@ -853,8 +858,8 @@ public class Client { ### 类图 -- TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression -- Context:上下文,包含解释器之外的一些全局信息 +- TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression。 +- Context:上下文,包含解释器之外的一些全局信息。

@@ -1851,7 +1856,7 @@ No gumball dispensed ### 类图 - Strategy 接口定义了一个算法族,它们都具有 behavior() 方法。 -- Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(in Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。 +- Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。

diff --git a/notes/重构.md b/notes/重构.md index b5a834e0..e90fa84e 100644 --- a/notes/重构.md +++ b/notes/重构.md @@ -161,6 +161,7 @@ class Customer { ```java class Rental { + private int daysRented; private Movie movie; @@ -199,6 +200,7 @@ class Movie { ```java public class App { + public static void main(String[] args) { Customer customer = new Customer(); Rental rental1 = new Rental(1, new Movie(Movie.Type1)); @@ -236,6 +238,7 @@ public class App { ```java class Customer { + private List rentals = new ArrayList<>(); void addRental(Rental rental) { @@ -254,6 +257,7 @@ class Customer { ```java class Rental { + private int daysRented; private Movie movie; @@ -294,8 +298,6 @@ class Price2 implements Price { ``` ```java -package imp2; - class Price3 implements Price { @Override public double getCharge() { diff --git a/notes/集群.md b/notes/集群.md index 15657e43..338ddcb4 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -119,7 +119,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 首先了解一下正向代理与反向代理的区别: - 正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端; -- 反向代理:发生在服务器端,用户不知道代理的存在。 +- 反向代理:发生在服务器端,用户不知道反向代理的存在。 反向代理服务器位于源服务器前面,用户的请求需要先经过反向代理服务器才能到达源服务器。反向代理可以用来进行缓存、日志记录等,同时也可以用来做为负载均衡服务器。 @@ -153,7 +153,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 通过配置源服务器的虚拟 IP 地址和负载均衡服务器的 IP 地址一致,从而不需要修改 IP 地址就可以进行转发。也正因为 IP 地址一样,所以源服务器的响应不需要转发回负载均衡服务器,可以直接转发给客户端,避免了负载均衡服务器的成为瓶颈。 -这是一种三角传输模式,被称为直接路由,对于提供下载和视频服务的网站来说,直接路由避免了大量的网络传输数据经过负载均衡服务器。 +这是一种三角传输模式,被称为直接路由。对于提供下载和视频服务的网站来说,直接路由避免了大量的网络传输数据经过负载均衡服务器。 这是目前大型网站使用最广负载均衡转发方式,在 Linux 平台可以使用的负载均衡服务器为 LVS(Linux Virtual Server)。 @@ -185,7 +185,6 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - 占用过多内存; - 同步过程占用网络带宽以及服务器处理器时间。 -

## Session Server @@ -206,3 +205,4 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - [Session Management using Spring Session with JDBC DataStore](https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/) + diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 203c7ebf..87b3b033 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -89,24 +89,28 @@ Animal animal = new Cat(); ```java public class Instrument { + public void play() { System.out.println("Instument is playing..."); } } public class Wind extends Instrument { + public void play() { System.out.println("Wind is playing..."); } } public class Percussion extends Instrument { + public void play() { System.out.println("Percussion is playing..."); } } public class Music { + public static void main(String[] args) { List instruments = new ArrayList<>(); instruments.add(new Wind()); @@ -353,4 +357,3 @@ Vihicle .. N - [看懂 UML 类图和时序图](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization) - [UML 系列——时序图(顺序图)sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html) - [面向对象编程三大特性 ------ 封装、继承、多态](http://blog.csdn.net/jianyuerensheng/article/details/51602015) - From b99d1d5237fd134e10b41eb18a269bc7fab596e8 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 30 Aug 2018 20:28:09 +0800 Subject: [PATCH 041/136] auto commit --- notes/Java 虚拟机.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 1dc4d1d6..333c1418 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -268,7 +268,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了 以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。 - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程; -- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并形指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 +- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 ### 1. Serial 收集器 From bb2592f820012d6220462f6a18a28d80983aa3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Fri, 31 Aug 2018 21:46:11 +0800 Subject: [PATCH 042/136] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9f43ec8..27edaf24 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
- +
From 0b2d8ac6fdab50c7e4ed961d43ea33e17d48769b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 1 Sep 2018 01:22:24 +0800 Subject: [PATCH 043/136] auto commit --- notes/Docker.md | 32 ++---- notes/Git.md | 32 +++--- notes/HTTP.md | 46 +++++---- notes/Java 并发.md | 33 +++--- notes/Java 虚拟机.md | 6 +- notes/Linux.md | 10 +- notes/分布式.md | 26 +++-- notes/构建工具.md | 29 ++---- notes/消息队列.md | 2 +- notes/算法.md | 70 ++++++------- notes/缓存.md | 26 ++--- notes/计算机网络.md | 8 +- notes/设计模式.md | 228 +++++++++++++++++++----------------------- notes/重构.md | 6 +- notes/集群.md | 6 +- notes/面向对象思想.md | 5 +- 16 files changed, 263 insertions(+), 302 deletions(-) diff --git a/notes/Docker.md b/notes/Docker.md index 80108896..1b61a7fe 100644 --- a/notes/Docker.md +++ b/notes/Docker.md @@ -4,6 +4,7 @@ * [三、优势](#三优势) * [四、使用场景](#四使用场景) * [五、镜像与容器](#五镜像与容器) +* [参考资料](#参考资料) @@ -15,11 +16,6 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 Docker 可以不修改应用程序代码,不需要开发人员学习特定环境下的技术,就能够将现有的应用程序部署在其他机器中。 -参考资料: - -- [DOCKER 101: INTRODUCTION TO DOCKER WEBINAR RECAP](https://blog.docker.com/2017/08/docker-101-introduction-docker-webinar-recap/) -- [Docker 入门教程](http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html) - # 二、与虚拟机的比较 虚拟机也是一种虚拟化技术,它与 Docker 最大的区别在于它是通过模拟硬件,并在硬件上安装操作系统来实现。 @@ -40,30 +36,22 @@ Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程 而 Docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 Docker。 -参考资料: - -- [Docker container vs Virtual machine](http://www.bogotobogo.com/DevOps/Docker/Docker_Container_vs_Virtual_Machine.php) - # 三、优势 除了启动速度快以及占用资源少之外,Docker 具有以下优势: ## 更容易迁移 -Docker 可以提供一致性的运行环境,可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。 +提供一致性的运行环境,可以在不同的机器上进行迁移,而不用担心环境变化导致无法运行。 ## 更容易维护 -Docker 使用分层技术和镜像,使得应用可以更容易复用重复部分。复用程度越高,维护工作也越容易。 +使用分层技术和镜像,使得应用可以更容易复用重复部分。复用程度越高,维护工作也越容易。 ## 更容易扩展 可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。 -参考资料: - -- [为什么要使用 Docker?](https://yeasy.gitbooks.io/docker_practice/introduction/why.html) - # 四、使用场景 ## 持续集成 @@ -80,11 +68,6 @@ Docker 具有轻量级以及隔离性的特点,在将代码集成到一个 Doc Docker 轻量级的特点使得它很适合用于部署、维护、组合微服务。 -参考资料: - -- [What is Docker](https://www.docker.com/what-docker) -- [持续集成是什么?](http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html) - # 五、镜像与容器 镜像是一种静态的结构,可以看成面向对象里面的类,而容器是镜像的一个实例。 @@ -95,9 +78,14 @@ Docker 轻量级的特点使得它很适合用于部署、维护、组合微服

-参考资料: +# 参考资料 +- [DOCKER 101: INTRODUCTION TO DOCKER WEBINAR RECAP](https://blog.docker.com/2017/08/docker-101-introduction-docker-webinar-recap/) +- [Docker 入门教程](http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html) +- [Docker container vs Virtual machine](http://www.bogotobogo.com/DevOps/Docker/Docker_Container_vs_Virtual_Machine.php) - [How to Create Docker Container using Dockerfile](https://linoxide.com/linux-how-to/dockerfile-create-docker-container/) - [理解 Docker(2):Docker 镜像](http://www.cnblogs.com/sammyliu/p/5877964.html) - +- [为什么要使用 Docker?](https://yeasy.gitbooks.io/docker_practice/introduction/why.html) +- [What is Docker](https://www.docker.com/what-docker) +- [持续集成是什么?](http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html) diff --git a/notes/Git.md b/notes/Git.md index 4bb0a543..71ff502c 100644 --- a/notes/Git.md +++ b/notes/Git.md @@ -1,8 +1,7 @@ -* [学习资料](#学习资料) * [集中式与分布式](#集中式与分布式) -* [Git 的中心服务器](#git-的中心服务器) -* [Git 工作流](#git-工作流) +* [中心服务器](#中心服务器) +* [工作流](#工作流) * [分支实现](#分支实现) * [冲突](#冲突) * [Fast forward](#fast-forward) @@ -11,16 +10,10 @@ * [SSH 传输设置](#ssh-传输设置) * [.gitignore 文件](#gitignore-文件) * [Git 命令一览](#git-命令一览) +* [参考资料](#参考资料) -# 学习资料 - -- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) -- [图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) -- [廖雪峰 : Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) -- [Learn Git Branching](https://learngitbranching.js.org/) - # 集中式与分布式 Git 属于分布式版本控制系统,而 SVN 属于集中式。 @@ -33,11 +26,13 @@ Git 属于分布式版本控制系统,而 SVN 属于集中式。 分布式版本控制新建分支、合并分支操作速度非常快,而集中式版本控制新建一个分支相当于复制一份完整代码。 -# Git 的中心服务器 +# 中心服务器 -Git 的中心服务器用来交换每个用户的修改。没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。Github 就是一种 Git 中心服务器。 +中心服务器用来交换每个用户的修改,没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。 -# Git 工作流 +Github 就是一个中心服务器。 + +# 工作流

@@ -54,14 +49,14 @@ Git 版本库有一个称为 stage 的暂存区,还有自动创建的 master

-可以跳过暂存区域直接从分支中取出修改或者直接提交修改到分支中 +可以跳过暂存区域直接从分支中取出修改,或者直接提交修改到分支中。 - git commit -a 直接把所有文件的修改添加到暂缓区然后执行提交 - git checkout HEAD -- files 取出最后一次修改,可以用来进行回滚操作 # 分支实现 -Git 把每次提交都连成一条时间线。分支使用指针来实现,例如 master 分支指针指向时间线的最后一个节点,也就是最后一次提交。HEAD 指针指向的是当前分支。 +使用指针将每个提交连接成一条时间线,HEAD 指针指向当前分支指针。

@@ -69,7 +64,7 @@ Git 把每次提交都连成一条时间线。分支使用指针来实现,例

-每次提交只会让当前分支向前移动,而其它分支不会移动。 +每次提交只会让当前分支指针向前移动,而其它分支指针不会移动。

@@ -155,4 +150,9 @@ $ ssh-keygen -t rsa -C "youremail@example.com" 比较详细的地址:http://www.cheat-sheets.org/saved-copy/git-cheat-sheet.pdf +# 参考资料 +- [Git - 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) +- [图解 Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) +- [廖雪峰 : Git 教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) +- [Learn Git Branching](https://learngitbranching.js.org/) diff --git a/notes/HTTP.md b/notes/HTTP.md index 537b24fe..aae807e6 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -25,6 +25,7 @@ * [实体首部字段](#实体首部字段) * [五、具体应用](#五具体应用) * [Cookie](#cookie) + * [6. Secure](#6-secure) * [缓存](#缓存) * [连接管理](#连接管理) * [内容协商](#内容协商) @@ -310,7 +311,7 @@ HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使 Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。 -Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB。 +Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(本地存储和会话存储)或 IndexedDB。 ### 1. 用途 @@ -348,7 +349,17 @@ Cookie: yummy_cookie=choco; tasty_cookie=strawberry Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; ``` -### 4. JavaScript 获取 Cookie +### 4. 作用域 + +Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。 + +Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配: + +- /docs +- /docs/Web/ +- /docs/Web/HTTP + +### 5. JavaScript 通过 `Document.cookie` 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie。 @@ -358,9 +369,7 @@ document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie); ``` -### 5. Secure 和 HttpOnly - -标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 +### 6. HttpOnly 标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 @@ -368,15 +377,9 @@ console.log(document.cookie); Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly ``` -### 6. 作用域 +## 6. Secure -Domain 标识指定了哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如 developer.mozilla.org)。 - -Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配: - -- /docs -- /docs/Web/ -- /docs/Web/HTTP +标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 ### 7. Session @@ -387,8 +390,7 @@ Session 可以存储在服务器上的文件、数据库或者内存中。也可 使用 Session 维护用户登录状态的过程如下: - 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中; -- 服务器验证该用户名和密码; -- 如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID; +- 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID; - 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中; - 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。 @@ -462,13 +464,13 @@ Cache-Control: max-age=31536000 Expires 首部字段也可以用于告知缓存服务器该资源什么时候会过期。 -- 在 HTTP/1.1 中,会优先处理 max-age 指令; -- 在 HTTP/1.0 中,max-age 指令会被忽略掉。 - ```html Expires: Wed, 04 Jul 2012 08:26:05 GMT ``` +- 在 HTTP/1.1 中,会优先处理 max-age 指令; +- 在 HTTP/1.0 中,max-age 指令会被忽略掉。 + ### 4. 缓存验证 需要先了解 ETag 首部字段的含义,它是资源的唯一标识。URL 不能唯一表示资源,例如 `http://www.google.com/` 有中文和英文两个资源,只有 ETag 才能对这两个资源进行唯一标识。 @@ -727,7 +729,7 @@ HTTPs 的报文摘要功能之所以安全,是因为它结合了加密和认 ## HTTP/1.x 缺陷 - HTTP/1.x 实现简单是以牺牲性能为代价的: +HTTP/1.x 实现简单是以牺牲性能为代价的: - 客户端需要使用多个连接才能实现并发和缩短延迟; - 不会压缩请求和响应首部,从而导致不必要的网络流量; @@ -741,9 +743,9 @@ HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式 在通信过程中,只会有一个 TCP 连接存在,它承载了任意数量的双向数据流(Stream)。 -- 一个数据流都有一个唯一标识符和可选的优先级信息,用于承载双向信息。 -- 消息(Message)是与逻辑请求或响应消息对应的完整的一系列帧。 -- 帧(Fram)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。 +- 一个数据流(Stream)都有一个唯一标识符和可选的优先级信息,用于承载双向信息。 +- 消息(Message)是与逻辑请求或响应对应的完整的一系列帧。 +- 帧(Frame)是最小的通信单位,来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 1403f764..03aaa9fd 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -637,6 +637,7 @@ B ```java public class WaitNotifyExample { + public synchronized void before() { System.out.println("before"); notifyAll(); @@ -674,12 +675,15 @@ after ## await() signal() signalAll() -java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 +java.util.concurrent 类库中提供了 Condition 类来实现线程之间的协调,可以在 Condition 上调用 await() 方法使线程等待,其它线程调用 signal() 或 signalAll() 方法唤醒等待的线程。 + +相比于 wait() 这种等待方式,await() 可以指定等待的条件,因此更加灵活。 使用 Lock 来获取一个 Condition 对象。 ```java public class AwaitSignalExample { + private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); @@ -809,7 +813,7 @@ before..before..before..before..before..before..before..before..before..before.. ## Semaphore -Semaphore 就是操作系统中的信号量,可以控制对互斥资源的访问线程数。 +Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的访问线程数。

@@ -1098,11 +1102,11 @@ Java 内存模型定义了 8 个操作来完成主内存和工作内存的交互 Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性,例如对一个 int 类型的变量执行 assign 赋值操作,这个操作就是原子性的。但是 Java 内存模型允许虚拟机将没有被 volatile 修饰的 64 位数据(long,double)的读写操作划分为两次 32 位的操作来进行,即 load、store、read 和 write 操作可以不具备原子性。 -有一个错误认识就是,int 等原子性的变量在多线程环境中不会出现线程安全问题。前面的线程不安全示例代码中,cnt 变量属于 int 类型变量,1000 个线程对它进行自增操作之后,得到的值为 997 而不是 1000。 +有一个错误认识就是,int 等原子性的类型在多线程环境中不会出现线程安全问题。前面的线程不安全示例代码中,cnt 属于 int 类型变量,1000 个线程对它进行自增操作之后,得到的值为 997 而不是 1000。 为了方便讨论,将内存间的交互操作简化为 3 个:load、assign、store。 -下图演示了两个线程同时对 cnt 变量进行操作,load、assign、store 这一系列操作整体上看不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入该变量的值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。 +下图演示了两个线程同时对 cnt 进行操作,load、assign、store 这一系列操作整体上看不具备原子性,那么在 T1 修改 cnt 并且还没有将修改后的值写入主内存,T2 依然可以读入旧值。可以看出,这两个线程虽然执行了两次自增运算,但是主内存中 cnt 的值最后为 1 而不是 2。因此对 int 类型读写操作满足原子性只是说明 load、assign、store 这些单个操作具备原子性。

@@ -1200,9 +1204,7 @@ public static void main(String[] args) throws InterruptedException { ### 3. 有序性 -有序性是指:在本线程内观察,所有操作都是有序的。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。 - -在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。 +有序性是指:在本线程内观察,所有操作都是有序的。在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。在 Java 内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。 volatile 关键字通过添加内存屏障的方式来禁止指令重排,即重排序时不能把后面的指令放到内存屏障之前。 @@ -1413,7 +1415,7 @@ synchronized 和 ReentrantLock。 **(二)AtomicInteger** -J.U.C 包里面的整数原子类 AtomicInteger,其中的 compareAndSet() 和 getAndIncrement() 等方法都使用了 Unsafe 类的 CAS 操作。 +J.U.C 包里面的整数原子类 AtomicInteger 的方法调用了 Unsafe 类的 CAS 操作。 以下代码使用了 AtomicInteger 执行了自增的操作。 @@ -1425,7 +1427,7 @@ public void add() { } ``` -以下代码是 incrementAndGet() 的源码,它调用了 unsafe 的 getAndAddInt() 。 +以下代码是 incrementAndGet() 的源码,它调用了 Unsafe 的 getAndAddInt() 。 ```java public final int incrementAndGet() { @@ -1463,9 +1465,6 @@ J.U.C 包提供了一个带有标记的原子引用类 AtomicStampedReference 多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在虚拟机栈中,属于线程私有的。 ```java -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - public class StackClosedExample { public void add100() { int cnt = 0; @@ -1555,7 +1554,7 @@ public class ThreadLocalExample1 {

-每个 Thread 都有一个 ThreadLocal.ThreadLocalMap 对象,Thread 类中就定义了 ThreadLocal.ThreadLocalMap 成员。 +每个 Thread 都有一个 ThreadLocal.ThreadLocalMap 对象。 ```java /* ThreadLocal values pertaining to this thread. This map is maintained @@ -1686,15 +1685,15 @@ JDK 1.6 引入了偏向锁和轻量级锁,从而让锁拥有了四个状态: - 缩小同步范围,从而减少锁争用。例如对于 synchronized,应该尽量使用同步块而不是同步方法。 -- 多用同步工具少用 wait() 和 notify()。首先,CountDownLatch, CyclicBarrier, Semaphore 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现复杂控制流;其次,这些同步类是由最好的企业编写和维护,在后续的 JDK 中还会不断优化和完善,使用这些更高等级的同步工具你的程序可以不费吹灰之力获得优化。 +- 多用同步工具少用 wait() 和 notify()。首先,CountDownLatch, CyclicBarrier, Semaphore 和 Exchanger 这些同步类简化了编码操作,而用 wait() 和 notify() 很难实现复杂控制流;其次,这些同步类是由最好的企业编写和维护,在后续的 JDK 中还会不断优化和完善。 + +- 使用 BlockingQueue 实现生产者消费者问题。 - 多用并发集合少用同步集合,例如应该使用 ConcurrentHashMap 而不是 Hashtable。 - 使用本地变量和不可变类来保证线程安全。 -- 使用线程池而不是直接创建 Thread 对象,这是因为创建线程代价很高,线程池可以有效地利用有限的线程来启动任务。 - -- 使用 BlockingQueue 实现生产者消费者问题。 +- 使用线程池而不是直接创建线程,这是因为创建线程代价很高,线程池可以有效地利用有限的线程来启动任务。 # 参考资料 diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 2b565cb5..333c1418 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -138,8 +138,8 @@ public class ReferenceCountingGC { Java 虚拟机使用该算法来判断对象是否可被回收,在 Java 中 GC Roots 一般包含以下内容: -- 虚拟机栈中引用的对象 -- 本地方法栈中引用的对象 +- 虚拟机栈中局部变量表中引用的对象 +- 本地方法栈中 JNI 中引用的对象 - 方法区中类静态属性引用的对象 - 方法区中的常量引用的对象 @@ -268,7 +268,7 @@ HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了 以上是 HotSpot 虚拟机中的 7 个垃圾收集器,连线表示垃圾收集器可以配合使用。 - 单线程与多线程:单线程指的是垃圾收集器只使用一个线程进行收集,而多线程使用多个线程; -- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并形指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 +- 串行与并行:串行指的是垃圾收集器与用户程序交替执行,这意味着在执行垃圾收集的时候需要停顿用户程序;并行指的是垃圾收集器和用户程序同时执行。除了 CMS 和 G1 之外,其它垃圾收集器都是以串行的方式执行。 ### 1. Serial 收集器 diff --git a/notes/Linux.md b/notes/Linux.md index 73a2e9ec..4ba647a7 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -644,7 +644,7 @@ locate 使用 /var/lib/mlocate/ 这个数据库来进行搜索,它存储在内 example: find . -name "shadow*" ``` -(一)与时间有关的选项 +**① 与时间有关的选项** ```html -mtime n :列出在 n 天前的那一天修改过内容的文件 @@ -657,7 +657,7 @@ example: find . -name "shadow*"

-(二)与文件拥有者和所属群组有关的选项 +**② 与文件拥有者和所属群组有关的选项** ```html -uid n @@ -668,7 +668,7 @@ example: find . -name "shadow*" -nogroup:搜索所属群组不存在于 /etc/group 的文件 ``` -(三)与文件权限和名称有关的选项 +**③ 与文件权限和名称有关的选项** ```html -name filename @@ -1038,9 +1038,7 @@ $ grep -n 'go\{2,5\}g' regular_express.txt ## printf -用于格式化输出。 - -它不属于管道命令,在给 printf 传数据时需要使用 $( ) 形式。 +用于格式化输出。它不属于管道命令,在给 printf 传数据时需要使用 $( ) 形式。 ```html $ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt) diff --git a/notes/分布式.md b/notes/分布式.md index e98f2860..113837ce 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -29,18 +29,18 @@ # 一、分布式锁 -在单机场景下,可以使用 Java 提供的内置锁来实现进程同步。但是在分布式场景下,需要同步的进程可能位于不同的节点上,那么就需要使用分布式锁。 +在单机场景下,可以使用语言的内置锁来实现进程同步。但是在分布式场景下,需要同步的进程可能位于不同的节点上,那么就需要使用分布式锁。 阻塞锁通常使用互斥量来实现: -- 互斥量为 1 表示有其它进程在使用锁,此时处于锁定状态; -- 互斥量为 0 表示未锁定状态。 +- 互斥量为 0 表示有其它进程在使用锁,此时处于锁定状态; +- 互斥量为 1 表示未锁定状态。 -1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示,存在表示互斥量为 1。 +1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示。 ## 数据库的唯一索引 -当想要获得锁时,就向表中插入一条记录,释放锁时就删除这条记录。唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否存于锁定状态。 +获得锁时向表中插入一条记录,释放锁时删除这条记录。唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否存于锁定状态。 存在以下几个问题: @@ -91,11 +91,11 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ### 5. 会话超时 -如果一个已经获得锁的会话超时了,因为创建的是临时节点,所以该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库的唯一索引实现分布式锁的释放锁失败问题。 +如果一个已经获得锁的会话超时了,因为创建的是临时节点,所以该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库的唯一索引实现的分布式锁释放锁失败问题。 ### 6. 羊群效应 -一个节点未获得锁,需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 +一个节点未获得锁,只需要监听自己的前一个子节点,这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望它的后一个子节点收到通知。 # 二、分布式事务 @@ -159,9 +159,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ## 一致性 -一致性指的是多个数据副本是否能保持一致的特性。 - -在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。 +一致性指的是多个数据副本是否能保持一致的特性,在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。 对系统的一个数据更新成功之后,如果所有用户都能够读取到最新的值,该系统就被认为具有强一致性。 @@ -169,7 +167,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操,请求总是能够在有限的时间内返回结果。 ## 分区容忍性 @@ -179,9 +177,9 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 ## 权衡 -在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际在是要在可用性和一致性之间做权衡。 +在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际上是要在可用性和一致性之间做权衡。 -可用性和一致性往往是冲突的,很难都使它们同时满足。在多个节点之间进行数据同步时, +可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时, - 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成; - 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。 @@ -204,7 +202,7 @@ BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思 ## 软状态 -指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在延时。 +指允许系统中的数据存在中间状态,并认为该中间状态不会影响系统整体可用性,即允许系统不同节点的数据副本之间进行同步的过程存在时延。 ## 最终一致性 diff --git a/notes/构建工具.md b/notes/构建工具.md index ce157934..34fef54b 100644 --- a/notes/构建工具.md +++ b/notes/构建工具.md @@ -1,11 +1,12 @@ -* [一、什么是构建工具](#一什么是构建工具) +* [一、构建工具的作用](#一构建工具的作用) * [二、Java 主流构建工具](#二java-主流构建工具) * [三、Maven](#三maven) +* [参考资料](#参考资料) -# 一、什么是构建工具 +# 一、构建工具的作用 构建工具是用于构建项目的自动化工具,主要包含以下工作: @@ -29,10 +30,6 @@ 不再需要通过 FTP 将 Jar 包上传到服务器上。 -参考资料: - -- [What is a build tool?](https://stackoverflow.com/questions/7249871/what-is-a-build-tool) - # 二、Java 主流构建工具 主要包括 Ant、Maven 和 Gradle。 @@ -72,12 +69,6 @@ dependencies { } ``` -参考资料: - -- [Java Build Tools Comparisons: Ant vs Maven vs Gradle](https://programmingmitra.blogspot.com/2016/05/java-build-tools-comparisons-ant-vs.html) -- [maven 2 gradle](http://sagioto.github.io/maven2gradle/) -- [新一代构建工具 gradle](https://www.imooc.com/learn/833) - # 三、Maven ## 概述 @@ -114,7 +105,7 @@ POM 代表项目对象模型,它是一个 XML 文件,保存在项目根目 ## 依赖原则 -### 依赖路径最短优先原则 +### 1. 依赖路径最短优先原则 ```html A -> B -> C -> X(1.0) @@ -122,7 +113,7 @@ A -> D -> X(2.0) ``` 由于 X(2.0) 路径最短,所以使用 X(2.0)。 -### 声明顺序优先原则 +### 2. 声明顺序优先原则 ```html A -> B -> X(1.0) @@ -131,7 +122,7 @@ A -> C -> X(2.0) 在 POM 中最先声明的优先,上面的两个依赖如果先声明 B,那么最后使用 X(1.0)。 -### 覆写优先原则 +### 3. 覆写优先原则 子 POM 内声明的依赖优先于父 POM 中声明的依赖。 @@ -139,9 +130,11 @@ A -> C -> X(2.0) 找到 Maven 加载的 Jar 包版本,使用 `mvn dependency:tree` 查看依赖树,根据依赖原则来调整依赖在 POM 文件的声明顺序。 -参考资料: +# 参考资料 - [POM Reference](http://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification) - - +- [What is a build tool?](https://stackoverflow.com/questions/7249871/what-is-a-build-tool) +- [Java Build Tools Comparisons: Ant vs Maven vs Gradle](https://programmingmitra.blogspot.com/2016/05/java-build-tools-comparisons-ant-vs.html) +- [maven 2 gradle](http://sagioto.github.io/maven2gradle/) +- [新一代构建工具 gradle](https://www.imooc.com/learn/833) diff --git a/notes/消息队列.md b/notes/消息队列.md index 209d962a..bc80894d 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -40,7 +40,7 @@ 发送者将消息发送给消息队列之后,不需要同步等待消息接收者处理完毕,而是立即返回进行其它操作。消息接收者从消息队列中订阅消息之后异步处理。 -例如在注册流程中通常需要发送验证邮件来确保注册用户的身份合法,可以使用消息队列使发送验证邮件的操作异步处理,用户在填写完注册信息之后就可以完成注册,而将发送验证邮件这一消息发送到消息队列中。 +例如在注册流程中通常需要发送验证邮件来确保注册用户身份的合法性,可以使用消息队列使发送验证邮件的操作异步处理,用户在填写完注册信息之后就可以完成注册,而将发送验证邮件这一消息发送到消息队列中。 只有在业务流程允许异步处理的情况下才能这么做,例如上面的注册流程中,如果要求用户对验证邮件进行点击之后才能完成注册的话,就不能再使用消息队列。 diff --git a/notes/算法.md b/notes/算法.md index 53edc1c1..cb83830b 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -379,7 +379,7 @@ public class Insertion> extends Sort { 对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。 -希尔排序的出现就是为了改进插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 +希尔排序的出现就是为了解决插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。 @@ -571,15 +571,15 @@ private int partition(T[] nums, int l, int h) { ### 4. 算法改进 -(一)切换到插入排序 +#### 4.1 切换到插入排序 因为快速排序在小数组中也会递归调用自己,对于小数组,插入排序比快速排序的性能更好,因此在小数组中可以切换到插入排序。 -(二)三数取中 +#### 4.2 三数取中 最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。人们发现取 3 个元素并将大小居中的元素作为切分元素的效果最好。 -(三)三向切分 +#### 4.3 三向切分 对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。 @@ -645,7 +645,7 @@ public T select(T[] nums, int k) { 堆的某个节点的值总是大于等于子节点的值,并且堆是一颗完全二叉树。 -堆可以用数组来表示,因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。 +堆可以用数组来表示,这是因为堆是完全二叉树,而完全二叉树很容易就存储在数组中。位置 k 的节点的父节点位置为 k/2,而它的两个子节点的位置分别为 2k 和 2k+1。这里不使用数组索引为 0 的位置,是为了更清晰地描述节点的位置关系。

@@ -739,15 +739,15 @@ public T delMax() { ### 5. 堆排序 -由于堆可以很容易得到最大的元素并删除它,不断地进行这种操作可以得到一个递减序列。如果把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列。因此很容易使用堆来进行排序。并且堆排序是原地排序,不占用额外空间。 +把最大元素和当前堆中数组的最后一个元素交换位置,并且不删除它,那么就可以得到一个从尾到头的递减序列,从正向来看就是一个递增序列,这就是堆排序。 -(一)构建堆 +#### 5.1 构建堆 -无序数组建立堆最直接的方法是从左到右遍历数组,然后进行上浮操作。一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。 +无序数组建立堆最直接的方法是从左到右遍历数组进行上浮操作。一个更高效的方法是从右至左进行下沉操作,如果一个节点的两个节点都已经是堆有序,那么进行下沉操作可以使得这个节点为根节点的堆有序。叶子节点不需要进行下沉操作,可以忽略叶子节点的元素,因此只需要遍历一半的元素即可。

-(二)交换堆顶元素与最后一个元素 +#### 5.2 交换堆顶元素与最后一个元素 交换之后需要进行下沉操作维持堆的有序状态。 @@ -804,7 +804,7 @@ public class HeapSort> extends Sort { ### 1. 排序算法的比较 -| 算法 | 稳定 | 时间复杂度 | 空间复杂度 | 备注 | +| 算法 | 稳定性 | 时间复杂度 | 空间复杂度 | 备注 | | :---: | :---: |:---: | :---: | :---: | | 选择排序 | × | N2 | 1 | | | 冒泡排序 | √ | N2 | 1 | | @@ -815,7 +815,7 @@ public class HeapSort> extends Sort { | 归并排序 | √ | NlogN | N | | | 堆排序 | × | NlogN | 1 | | | -快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN,这里的 c 比其他线性对数级别的排序算法都要小。使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。 +快速排序是最快的通用排序算法,它的内循环的指令很少,而且它还能利用缓存,因为它总是顺序地访问数据。它的运行时间近似为 \~cNlogN,这里的 c 比其它线性对数级别的排序算法都要小。使用三向切分快速排序,实际应用中可能出现的某些分布的输入能够达到线性级别,而其它排序算法仍然需要线性对数时间。 ### 2. Java 的排序算法实现 @@ -882,7 +882,6 @@ public class QuickFindUF extends UF { @Override public void union(int p, int q) { - int pID = find(p); int qID = find(q); @@ -917,7 +916,6 @@ public class QuickUnionUF extends UF { @Override public int find(int p) { - while (p != id[p]) { p = id[p]; } @@ -927,7 +925,6 @@ public class QuickUnionUF extends UF { @Override public void union(int p, int q) { - int pRoot = find(p); int qRoot = find(q); @@ -938,7 +935,7 @@ public class QuickUnionUF extends UF { } ``` -这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为触点的数目。 +这种方法可以快速进行 union 操作,但是 find 操作和树高成正比,最坏的情况下树的高度为节点的数目。

@@ -1588,7 +1585,7 @@ public class BST, Value> implements OrderedST
@@ -1806,9 +1803,9 @@ private List keys(Node x, Key l, Key h) { } ``` -### 10. 性能分析 +### 10. 分析 -复杂度:二叉查找树所有操作在最坏的情况下所需要的时间都和树的高度成正比。 +二叉查找树所有操作在最坏的情况下所需要的时间都和树的高度成正比。 ## 2-3 查找树 @@ -1838,7 +1835,7 @@ private List keys(Node x, Key l, Key h) { ## 红黑树 -2-3 查找树需要用到 2- 节点和 3- 节点,红黑树使用红链接来实现 3- 节点。指向一个节点的链接颜色如果为红色,那么这个节点和上层节点表示的是一个 3- 节点,而黑色则是普通链接。 +红黑树是 2-3 查找树,但它不需要分别定义 2- 节点和 3- 节点,而是在普通的二叉查找树之上,为节点添加颜色。指向一个节点的链接颜色如果为红色,那么这个节点和上层节点表示的是一个 3- 节点,而黑色则是普通链接。

@@ -1853,6 +1850,7 @@ private List keys(Node x, Key l, Key h) { ```java public class RedBlackBST, Value> extends BST { + private static final boolean RED = true; private static final boolean BLACK = false; @@ -2008,16 +2006,17 @@ int hash = (((day * R + month) % M) * R + year) % M; R 通常取 31。 -Java 中的 hashCode() 实现了 hash 函数,但是默认使用对象的内存地址值。在使用 hashCode() 函数时,应当结合除留余数法来使用。因为内存地址是 32 位整数,我们只需要 31 位的非负整数,因此应当屏蔽符号位之后再使用除留余数法。 +Java 中的 hashCode() 实现了哈希函数,但是默认使用对象的内存地址值。在使用 hashCode() 时,应当结合除留余数法来使用。因为内存地址是 32 位整数,我们只需要 31 位的非负整数,因此应当屏蔽符号位之后再使用除留余数法。 ```java int hash = (x.hashCode() & 0x7fffffff) % M; ``` -使用 Java 自带的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode(): +使用 Java 的 HashMap 等自带的哈希表实现时,只需要去实现 Key 类型的 hashCode() 函数即可。Java 规定 hashCode() 能够将键均匀分布于所有的 32 位整数,Java 中的 String、Integer 等对象的 hashCode() 都能实现这一点。以下展示了自定义类型如何实现 hashCode(): ```java public class Transaction { + private final String who; private final Date when; private final double amount; @@ -2039,17 +2038,17 @@ public class Transaction { } ``` -### 2. 基于拉链法的散列表 +### 2. 拉链法 拉链法使用链表来存储 hash 值相同的键,从而解决冲突。 查找需要分两步,首先查找 Key 所在的链表,然后在链表中顺序查找。 -对于 N 个键,M 条链表 (N>M),如果 hash 函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。 +对于 N 个键,M 条链表 (N>M),如果哈希函数能够满足均匀性的条件,每条链表的大小趋向于 N/M,因此未命中的查找和插入操作所需要的比较次数为 \~N/M。

-### 3. 基于线性探测法的散列表 +### 3. 线性探测法 线性探测法使用空位来解决冲突,当冲突发生时,向前探测一个空位来存储冲突的键。 @@ -2059,6 +2058,7 @@ public class Transaction { ```java public class LinearProbingHashST implements UnorderedST { + private int N = 0; private int M = 16; private Key[] keys; @@ -2084,7 +2084,7 @@ public class LinearProbingHashST implements UnorderedST } ``` -**(一)查找** +#### 3.1 查找 ```java public Value get(Key key) { @@ -2096,7 +2096,7 @@ public Value get(Key key) { } ``` -**(二)插入** +#### 3.2 插入 ```java public void put(Key key, Value value) { @@ -2118,7 +2118,7 @@ private void putInternal(Key key, Value value) { } ``` -**(三)删除** +#### 3.3 删除 删除操作应当将右侧所有相邻的键值对重新插入散列表中。 @@ -2151,7 +2151,7 @@ public void delete(Key key) { } ``` -**(四)调整数组大小** +#### 3.5 调整数组大小 线性探测法的成本取决于连续条目的长度,连续条目也叫聚簇。当聚簇很长时,在查找和插入时也需要进行很多次探测。例如下图中 2\~5 位置就是一个聚簇。 @@ -2235,15 +2235,15 @@ public class SparseVector { 这是一个经典的递归问题,分为三步求解: -- 将 n-1 个圆盘从 from -> buffer +① 将 n-1 个圆盘从 from -> buffer

-- 将 1 个圆盘从 from -> to +② 将 1 个圆盘从 from -> to

-- 将 n-1 个圆盘从 buffer -> to +③ 将 n-1 个圆盘从 buffer -> to

@@ -2281,9 +2281,9 @@ from H1 to H3 ## 哈夫曼编码 -哈夫曼编码根据数据出现的频率对数据进行编码,从而压缩原始数据。 +根据数据出现的频率对数据进行编码,从而压缩原始数据。 -例如对于文本文件,其中各种字符出现的次数如下: +例如对于一个文本文件,其中各种字符出现的次数如下: - a : 10 - b : 20 @@ -2294,7 +2294,7 @@ from H1 to H3 首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 -生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到根节点,根节点代表的字符的编码就是这个路径编码。 +生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。

diff --git a/notes/缓存.md b/notes/缓存.md index ed834253..26d96be1 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -26,16 +26,16 @@ ## 淘汰策略 -- FIFO(First In First Out):先进先出策略,在实时性的场景下,需要经常访问最新的数据,那么就可以使用 FIFO,使最先进入的数据(最晚的数据)被淘汰。 +- FIFO(First In First Out):先进先出策略,在实时性的场景下,需要经常访问最新的数据,那么就可以使用 FIFO,使得最先进入的数据(最晚的数据)被淘汰。 -- LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最远的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 +- LRU(Least Recently Used):最近最久未使用策略,优先淘汰最久未使用的数据,也就是上次被访问时间距离现在最久的数据。该策略可以保证内存中的数据都是热点数据,也就是经常被访问的数据,从而保证缓存命中率。 # 二、LRU -以下是一个基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: +以下是基于 双向链表 + HashMap 的 LRU 算法实现,对算法的解释如下: -- 最基本的思路是当访问某个节点时,将其从原来的位置删除,并重新插入到链表头部,这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就删除链表尾部的节点。 -- 为了使删除操作时间复杂度为 O(1),那么就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。 +- 访问某个节点时,将其从原来的位置删除,并重新插入到链表头部。这样就能保证链表尾部存储的就是最近最久未使用的节点,当节点数量大于缓存最大空间时就淘汰链表尾部的节点。 +- 为了使删除操作时间复杂度为 O(1),就不能采用遍历的方式找到某个节点。HashMap 存储着 Key 到节点的映射,通过 Key 就能以 O(1) 的时间得到节点,然后再以 O(1) 的时间将其从双向队列中删除。 ```java public class LRU implements Iterable { @@ -152,7 +152,7 @@ public class LRU implements Iterable { ## 反向代理 -反向代理位于服务器之前,请求与响应都需要经过反向代理。通过将数据缓存在反向代理,在用户请求时就可以直接使用缓存进行响应。 +反向代理位于服务器之前,请求与响应都需要经过反向代理。通过将数据缓存在反向代理,在用户请求反向代理时就可以直接使用缓存进行响应。 ## 本地缓存 @@ -166,7 +166,7 @@ public class LRU implements Iterable { ## 数据库缓存 -MySQL 等数据库管理系统具有自己的查询缓存机制来提高 SQL 查询效率。 +MySQL 等数据库管理系统具有自己的查询缓存机制来提高查询效率。 # 四、CDN @@ -193,9 +193,9 @@ CDN 主要有以下优点: ## 缓存雪崩 -指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都去到达数据库。 +指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。 -在存在缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。 +在有缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。 解决方案: @@ -233,7 +233,7 @@ CDN 主要有以下优点: # 七、一致性哈希 -Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据失效的问题。 +Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了克服传统哈希分布在服务器节点数量变化时大量数据迁移的问题。 ## 基本原理 @@ -241,7 +241,7 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了

-一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它前一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。 +一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它后一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。

@@ -249,7 +249,9 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了 上面描述的一致性哈希存在数据分布不均匀的问题,节点存储的数据量有可能会存在很大的不同。 -数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得大,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 +数据不均匀主要是因为节点在哈希环上分布的不均匀,这种情况在节点数量很少的情况下尤其明显。 + +解决方式是通过增加虚拟节点,然后将虚拟节点映射到真实节点上。虚拟节点的数量比真实节点来得多,那么虚拟节点在哈希环上分布的均匀性就会比原来的真实节点好,从而使得数据分布也更加均匀。 # 参考资料 diff --git a/notes/计算机网络.md b/notes/计算机网络.md index 99a6fb43..3a08e2a0 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -59,7 +59,7 @@ 网络把主机连接起来,而互联网是把多种不同的网络连接起来,因此互联网是网络的网络。 -

+

## ISP @@ -304,7 +304,7 @@ PPP 的帧格式: MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标识网络适配器(网卡)。 -一台主机拥有多少个适配器就有多少个 MAC 地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器,因此就有两个 MAC 地址。 +一台主机拥有多少个网络适配器就有多少个 MAC 地址。例如笔记本电脑普遍存在无线网络适配器和有线网络适配器,因此就有两个 MAC 地址。 ## 局域网 @@ -320,7 +320,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标 以太网是一种星型拓扑结构局域网。 -早期使用集线器进行连接,集线器是一种物理层设备,作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到同时从两个不同接口的帧,那么就发生了碰撞。 +早期使用集线器进行连接,集线器是一种物理层设备, 作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到同时从两个不同接口的帧,那么就发生了碰撞。 目前以太网使用交换机替代了集线器,交换机是一种链路层设备,它不会发生碰撞,能根据 MAC 地址进行存储转发。 @@ -488,7 +488,7 @@ Traceroute 发送的 IP 数据报封装的是无法交付的 UDP 用户数据报 - 172.16.0.0 \~ 172.31.255.255 - 192.168.0.0 \~ 192.168.255.255 -VPN 使用公用的互联网作为本机构各专用网之间的通信载体。专用指机构内的主机只与本机构内的其它主机通信;虚拟指“好像是”,而实际上并不是,它有经过公用的互联网。 +VPN 使用公用的互联网作为本机构各专用网之间的通信载体。专用指机构内的主机只与本机构内的其它主机通信;虚拟指好像是,而实际上并不是,它有经过公用的互联网。 下图中,场所 A 和 B 的通信经过互联网,如果场所 A 的主机 X 要和另一个场所 B 的主机 Y 通信,IP 数据报的源地址是 10.1.0.1,目的地址是 10.2.0.3。数据报先发送到与互联网相连的路由器 R1,R1 对内部数据进行加密,然后重新加上数据报的首部,源地址是路由器 R1 的全球地址 125.1.2.3,目的地址是路由器 R2 的全球地址 194.4.5.6。路由器 R2 收到数据报后将数据部分进行解密,恢复原来的数据报,此时目的地址为 10.2.0.3,就交付给 Y。 diff --git a/notes/设计模式.md b/notes/设计模式.md index 531595e3..82c09e6d 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -44,11 +44,11 @@ ## 1. 单例(Singleton) -### 意图 +### Intent 确保一个类只有一个实例,并提供该实例的全局访问点。 -### 类图 +### Class Diagram 使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。 @@ -56,13 +56,13 @@

-### 实现 +### Implementation -(一)懒汉式-线程不安全 +#### Ⅰ 懒汉式-线程不安全 以下实现中,私有静态变量 uniqueInstance 被延迟实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。 -这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么会有多个线程执行 `uniqueInstance = new Singleton();` 语句,这将导致多次实例化 uniqueInstance。 +这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 `if (uniqueInstance == null)` ,并且此时 uniqueInstance 为 null,那么会有多个线程执行 `uniqueInstance = new Singleton();` 语句,这将导致实例化多次 uniqueInstance。 ```java public class Singleton { @@ -81,9 +81,9 @@ public class Singleton { } ``` -(二)饿汉式-线程安全 +#### Ⅱ 饿汉式-线程安全 -线程不安全问题主要是由于 uniqueInstance 被多次实例化,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。 +线程不安全问题主要是由于 uniqueInstance 被实例化多次,采取直接实例化 uniqueInstance 的方式就不会产生线程不安全问题。 但是直接实例化的方式也丢失了延迟实例化带来的节约资源的好处。 @@ -91,11 +91,11 @@ public class Singleton { private static Singleton uniqueInstance = new Singleton(); ``` -(三)懒汉式-线程安全 +#### Ⅲ 懒汉式-线程安全 -只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了多次实例化 uniqueInstance 的问题。 +只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了实例化多次 uniqueInstance。 -但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,因此性能上有一定的损耗。 +但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,即使 uniqueInstance 已经被实例化了。这会让线程阻塞时间过程,因此该方法有性能问题,不推荐使用。 ```java public static synchronized Singleton getUniqueInstance() { @@ -106,7 +106,7 @@ public static synchronized Singleton getUniqueInstance() { } ``` -(四)双重校验锁-线程安全 +#### Ⅳ 双重校验锁-线程安全 uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。 @@ -133,7 +133,7 @@ public class Singleton { } ``` -考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 `uniqueInstance = new Singleton();` 这条语句,只是先后的问题,那么就会进行两次实例化,从而产生了两个实例。因此必须使用双重校验锁,也就是需要使用两个 if 语句。 +考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程都执行了 if 语句,那么两个线程都会进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 `uniqueInstance = new Singleton();` 这条语句,只是先后的问题,那么就会进行两次实例化。因此必须使用双重校验锁,也就是需要使用两个 if 语句。 ```java if (uniqueInstance == null) { @@ -145,19 +145,19 @@ if (uniqueInstance == null) { uniqueInstance 采用 volatile 关键字修饰也是很有必要的。`uniqueInstance = new Singleton();` 这段代码其实是分为三步执行。 -1. 分配内存空间 -2. 初始化对象 +1. 为 uniqueInstance 分配内存空间 +2. 初始化 uniqueInstance 3. 将 uniqueInstance 指向分配的内存地址 -但是由于 JVM 具有指令重排的特性,有可能执行顺序变为了 1>3>2,这在单线程情况下自然是没有问题。但如果是多线程下,有可能获得是一个还没有被初始化的实例,以致于程序出错。 +但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1>3>2。指令重排在单线程环境下不会出先问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。 使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。 -(五)静态内部类实现 +#### Ⅴ 静态内部类实现 -当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 `getUniqueInstance()` 方法从而触发 `SingletonHolder.INSTANCE` 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例。 +当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 `getUniqueInstance()` 方法从而触发 `SingletonHolder.INSTANCE` 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。 -这种方式不仅具有延迟初始化的好处,而且由虚拟机提供了对线程安全的支持。 +这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。 ```java public class Singleton { @@ -175,40 +175,11 @@ public class Singleton { } ``` -(六)枚举实现 +该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 -这是单例模式的最佳实践,它实现简单,并且在面对复杂的序列化或者反射攻击的时候,能够防止实例化多次。 +该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 -```java -public enum Singleton { - uniqueInstance; -} -``` - -考虑以下单例模式的实现,该 Singleton 在每次序列化的时候都会创建一个新的实例,为了保证只创建一个实例,必须声明所有字段都是 transient,并且提供一个 readResolve() 方法。 - -```java -public class Singleton implements Serializable { - - private static Singleton uniqueInstance; - - private Singleton() { - } - - public static synchronized Singleton getUniqueInstance() { - if (uniqueInstance == null) { - uniqueInstance = new Singleton(); - } - return uniqueInstance; - } -} -``` - -如果不使用枚举来实现单例模式,会出现反射攻击,因为通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象。如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。 - -从上面的讨论可以看出,解决序列化和反射攻击很麻烦,而枚举实现不会出现这两种问题,所以说枚举实现单例模式是最佳实践。 - -### 使用场景 +### Examples - Logger Classes - Configuration Classes @@ -223,11 +194,11 @@ public class Singleton implements Serializable { ## 2. 简单工厂(Simple Factory) -### 意图 +### Intent 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。 -### 类图 +### Class Diagram 简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 @@ -235,7 +206,7 @@ public class Singleton implements Serializable {

-### 实现 +### Implementation ```java public interface Product { @@ -303,11 +274,11 @@ public class Client { ## 3. 工厂方法(Factory Method) -### 意图 +### Intent 定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。 -### 类图 +### Class Diagram 在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。 @@ -315,7 +286,7 @@ public class Client {

-### 实现 +### Implementation ```java public abstract class Factory { @@ -363,11 +334,11 @@ public class ConcreteFactory2 extends Factory { ## 4. 抽象工厂(Abstract Factory) -### 意图 +### Intent 提供一个接口,用于创建 **相关的对象家族** 。 -### 类图 +### Class Diagram 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 @@ -379,7 +350,7 @@ public class ConcreteFactory2 extends Factory {

-### 代码实现 +### Implementation ```java public class AbstractProductA { @@ -461,15 +432,15 @@ public class Client { ## 5. 生成器(Builder) -### 意图 +### Intent 封装一个对象的构造过程,并允许按步骤构造。 -### 类图 +### Class Diagram

-### 实现 +### Implementation 以下是一个简易的 StringBuilder 实现,参考了 JDK 1.8 源码。 @@ -551,15 +522,15 @@ abcdefghijklmnopqrstuvwxyz ## 6. 原型模式(Prototype) -### 意图 +### Intent 使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。 -### 类图 +### Class Diagram

-### 实现 +### Implementation ```java public abstract class Prototype { @@ -610,17 +581,17 @@ abc ## 1. 责任链(Chain Of Responsibility) -### 意图 +### Intent 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。 -### 类图 +### Class Diagram - Handler:定义处理请求的接口,并且实现后继链(successor)

-### 实现 +### Implementation ```java public abstract class Handler { @@ -724,11 +695,16 @@ request2 is handle by ConcreteHandler2 ## 2. 命令(Command) -### 意图 +### Intent -将命令封装成对象中,以便使用命令来参数化其它对象,或者将命令对象放入队列中进行排队,或者将命令对象的操作记录到日志中,以及支持可撤销的操作。 +将命令封装成对象中,具有以下作用: -### 类图 +- 使用命令来参数化其它对象 +- 将命令放入队列中进行排队 +- 将命令的操作记录到日志中 +- 支持可撤销的操作 + +### Class Diagram - Command:命令 - Receiver:命令接收者,也就是命令真正的执行者 @@ -737,7 +713,7 @@ request2 is handle by ConcreteHandler2

-### 实现 +### Implementation 设计一个遥控器,可以控制电灯开关。 @@ -847,18 +823,18 @@ public class Client { ## 3. 解释器(Interpreter) -### 意图 +### Intent 为语言创建解释器,通常由语言的语法和语法分析来定义。 -### 类图 +### Class Diagram -- TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression -- Context:上下文,包含解释器之外的一些全局信息 +- TerminalExpression:终结符表达式,每个终结符都需要一个 TerminalExpression。 +- Context:上下文,包含解释器之外的一些全局信息。

-### 实现 +### Implementation 以下是一个规则检验器实现,具有 and 和 or 规则,通过规则可以构建一颗解析树,用来检验一个文本是否满足解析树定义的规则。 @@ -971,11 +947,11 @@ false ## 4. 迭代器(Iterator) -### 意图 +### Intent 提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。 -### 类图 +### Class Diagram - Aggregate 是聚合类,其中 createIterator() 方法可以产生一个 Iterator; - Iterator 主要定义了 hasNext() 和 next() 方法。 @@ -983,7 +959,7 @@ false

-### 实现 +### Implementation ```java public interface Aggregate { @@ -1059,18 +1035,18 @@ public class Client { ## 5. 中介者(Mediator) -### 意图 +### Intent 集中相关对象之间复杂的沟通和控制方式。 -### 类图 +### Class Diagram - Mediator:中介者,定义一个接口用于与各同事(Colleague)对象通信。 - Colleague:同事,相关对象

-### 实现 +### Implementation Alarm(闹钟)、CoffeePot(咖啡壶)、Calendar(日历)、Sprinkler(喷头)是一组相关的对象,在某个对象的事件产生时需要去操作其它对象,形成了下面这种依赖结构: @@ -1228,11 +1204,11 @@ doSprinkler() ## 6. 备忘录(Memento) -### 意图 +### Intent 在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。 -### 类图 +### Class Diagram - Originator:原始对象 - Caretaker:负责保存好备忘录 @@ -1240,7 +1216,7 @@ doSprinkler()

-### 实现 +### Implementation 以下实现了一个简单计算器程序,可以输入两个值,然后计算这两个值的和。备忘录模式允许将这两个值存储起来,然后在某个时刻用存储的状态进行恢复。 @@ -1405,7 +1381,7 @@ public class Client { ## 7. 观察者(Observer) -### 意图 +### Intent 定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。 @@ -1413,7 +1389,7 @@ public class Client {

-### 类图 +### Class Diagram 主题(Subject)具有注册和移除观察者、并通知所有观察者的功能,主题是通过维护一张观察者列表来实现这些操作的。 @@ -1421,7 +1397,7 @@ public class Client {

-### 实现 +### Implementation 天气数据布告板会在天气信息发生改变时更新其内容,布告板有多个,并且在将来会继续增加。 @@ -1540,15 +1516,15 @@ StatisticsDisplay.update: 1.0 1.0 1.0 ## 8. 状态(State) -### 意图 +### Intent 允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。 -### 类图 +### Class Diagram

-### 实现 +### Implementation 糖果销售机有多种状态,每种状态下销售机有不同的行为,状态可以发生转移,使得销售机的行为也发生改变。 @@ -1842,16 +1818,16 @@ No gumball dispensed ## 9. 策略(Strategy) -### 意图 +### Intent 定义一系列算法,封装每个算法,并使它们可以互换。 策略模式可以让算法独立于使用它的客户端。 -### 类图 +### Class Diagram - Strategy 接口定义了一个算法族,它们都具有 behavior() 方法。 -- Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(in Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。 +- Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。

@@ -1861,7 +1837,7 @@ No gumball dispensed 状态模式主要是用来解决状态转移的问题,当状态发生转移了,那么 Context 对象就会改变它的行为;而策略模式主要是用来封装一组可以互相替代的算法族,并且可以根据需要动态地去替换 Context 使用的算法。 -### 实现 +### Implementation 设计一个鸭子,它可以动态地改变叫声。这里的算法族是鸭子的叫声行为。 @@ -1930,17 +1906,17 @@ quack! ## 10. 模板方法(Template Method) -### 意图 +### Intent 定义算法框架,并将一些步骤的实现延迟到子类。 通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。 -### 类图 +### Class Diagram

-### 实现 +### Implementation 冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。 @@ -2031,11 +2007,11 @@ Tea.addCondiments ## 11. 访问者(Visitor) -### 意图 +### Intent 为一个对象结构(比如组合结构)增加新能力。 -### 类图 +### Class Diagram - Visitor:访问者,为每一个 ConcreteElement 声明一个 visit 操作 - ConcreteVisitor:具体访问者,存储遍历过程中的累计结果 @@ -2043,7 +2019,7 @@ Tea.addCondiments

-### 实现 +### Implementation ```java public interface Element { @@ -2238,17 +2214,17 @@ Number of items: 6 ## 12. 空对象(Null) -### 意图 +### Intent 使用什么都不做的空对象来代替 NULL。 一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。 -### 类图 +### Class Diagram

-### 实现 +### Implementation ```java public abstract class AbstractOperation { @@ -2294,17 +2270,17 @@ public class Client { ## 1. 适配器(Adapter) -### 意图 +### Intent 把一个类接口转换成另一个用户需要的接口。

-### 类图 +### Class Diagram

-### 实现 +### Implementation 鸭子(Duck)和火鸡(Turkey)拥有不同的叫声,Duck 的叫声调用 quack() 方法,而 Turkey 调用 gobble() 方法。 @@ -2365,18 +2341,18 @@ public class Client { ## 2. 桥接(Bridge) -### 意图 +### Intent 将抽象与实现分离开来,使它们可以独立变化。 -### 类图 +### Class Diagram - Abstraction:定义抽象类的接口 - Implementor:定义实现类接口

-### 实现 +### Implementation RemoteControl 表示遥控器,指代 Abstraction。 @@ -2518,11 +2494,11 @@ public class Client { ## 3. 组合(Composite) -### 意图 +### Intent 将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。 -### 类图 +### Class Diagram 组件(Component)类是组合类(Composite)和叶子类(Leaf)的父类,可以把组合类看成是树的中间节点。 @@ -2530,7 +2506,7 @@ public class Client {

-### 实现 +### Implementation ```java public abstract class Component { @@ -2652,17 +2628,17 @@ Composite:root ## 4. 装饰(Decorator) -### 意图 +### Intent 为对象动态添加功能。 -### 类图 +### Class Diagram 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。

-### 实现 +### Implementation 设计不同种类的饮料,饮料可以添加配料,比如可以添加牛奶,并且支持动态添加新配料。每增加一种配料,该饮料的价格就会增加,要求计算一种饮料的价格。 @@ -2759,15 +2735,15 @@ public class Client { ## 5. 外观(Facade) -### 意图 +### Intent 提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。 -### 类图 +### Class Diagram

-### 实现 +### Implementation 观看电影需要操作很多电器,使用外观模式实现一键看电影功能。 @@ -2814,11 +2790,11 @@ public class Client { ## 6. 享元(Flyweight) -### 意图 +### Intent 利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。 -### 类图 +### Class Diagram - Flyweight:享元对象 - IntrinsicState:内部状态,享元对象共享内部状态 @@ -2826,7 +2802,7 @@ public class Client {

-### 实现 +### Implementation ```java public interface Flyweight { @@ -2899,11 +2875,11 @@ Java 利用缓存来加速大量小对象的访问时间。 ## 7. 代理(Proxy) -### 意图 +### Intent 控制对其它对象的访问。 -### 类图 +### Class Diagram 代理有以下四类: @@ -2914,7 +2890,7 @@ Java 利用缓存来加速大量小对象的访问时间。

-### 实现 +### Implementation 以下是一个虚拟代理的实现,模拟了图片延迟加载的情况下使用与图片大小相等的临时内容去替换原始图片,直到图片加载完成才将图片显示出来。 diff --git a/notes/重构.md b/notes/重构.md index b5a834e0..e90fa84e 100644 --- a/notes/重构.md +++ b/notes/重构.md @@ -161,6 +161,7 @@ class Customer { ```java class Rental { + private int daysRented; private Movie movie; @@ -199,6 +200,7 @@ class Movie { ```java public class App { + public static void main(String[] args) { Customer customer = new Customer(); Rental rental1 = new Rental(1, new Movie(Movie.Type1)); @@ -236,6 +238,7 @@ public class App { ```java class Customer { + private List rentals = new ArrayList<>(); void addRental(Rental rental) { @@ -254,6 +257,7 @@ class Customer { ```java class Rental { + private int daysRented; private Movie movie; @@ -294,8 +298,6 @@ class Price2 implements Price { ``` ```java -package imp2; - class Price3 implements Price { @Override public double getCharge() { diff --git a/notes/集群.md b/notes/集群.md index 15657e43..338ddcb4 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -119,7 +119,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 首先了解一下正向代理与反向代理的区别: - 正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端; -- 反向代理:发生在服务器端,用户不知道代理的存在。 +- 反向代理:发生在服务器端,用户不知道反向代理的存在。 反向代理服务器位于源服务器前面,用户的请求需要先经过反向代理服务器才能到达源服务器。反向代理可以用来进行缓存、日志记录等,同时也可以用来做为负载均衡服务器。 @@ -153,7 +153,7 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 通过配置源服务器的虚拟 IP 地址和负载均衡服务器的 IP 地址一致,从而不需要修改 IP 地址就可以进行转发。也正因为 IP 地址一样,所以源服务器的响应不需要转发回负载均衡服务器,可以直接转发给客户端,避免了负载均衡服务器的成为瓶颈。 -这是一种三角传输模式,被称为直接路由,对于提供下载和视频服务的网站来说,直接路由避免了大量的网络传输数据经过负载均衡服务器。 +这是一种三角传输模式,被称为直接路由。对于提供下载和视频服务的网站来说,直接路由避免了大量的网络传输数据经过负载均衡服务器。 这是目前大型网站使用最广负载均衡转发方式,在 Linux 平台可以使用的负载均衡服务器为 LVS(Linux Virtual Server)。 @@ -185,7 +185,6 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - 占用过多内存; - 同步过程占用网络带宽以及服务器处理器时间。 -

## Session Server @@ -206,3 +205,4 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - [Session Management using Spring Session with JDBC DataStore](https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/) + diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 203c7ebf..87b3b033 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -89,24 +89,28 @@ Animal animal = new Cat(); ```java public class Instrument { + public void play() { System.out.println("Instument is playing..."); } } public class Wind extends Instrument { + public void play() { System.out.println("Wind is playing..."); } } public class Percussion extends Instrument { + public void play() { System.out.println("Percussion is playing..."); } } public class Music { + public static void main(String[] args) { List instruments = new ArrayList<>(); instruments.add(new Wind()); @@ -353,4 +357,3 @@ Vihicle .. N - [看懂 UML 类图和时序图](http://design-patterns.readthedocs.io/zh_CN/latest/read_uml.html#generalization) - [UML 系列——时序图(顺序图)sequence diagram](http://www.cnblogs.com/wolf-sun/p/UML-Sequence-diagram.html) - [面向对象编程三大特性 ------ 封装、继承、多态](http://blog.csdn.net/jianyuerensheng/article/details/51602015) - From f3d69c363fad4363863fb8436e59a41619ffbf5d Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 1 Sep 2018 01:23:33 +0800 Subject: [PATCH 044/136] auto commit --- notes/设计模式.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index eb838da7..82c09e6d 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -699,11 +699,6 @@ request2 is handle by ConcreteHandler2 将命令封装成对象中,具有以下作用: -<<<<<<< HEAD -======= -将命令封装成对象中,具有以下作用: - ->>>>>>> bb2592f820012d6220462f6a18a28d80983aa3f0 - 使用命令来参数化其它对象 - 将命令放入队列中进行排队 - 将命令的操作记录到日志中 From 66bc75d5d17cf09f8a0d747459b8c3336be28adb Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 1 Sep 2018 15:07:50 +0800 Subject: [PATCH 045/136] auto commit --- notes/设计模式.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index 82c09e6d..9d9ab38f 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -202,7 +202,7 @@ public class Singleton { 简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 -这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。因为客户类往往有多个,如果不使用简单工厂,所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 +这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。

@@ -228,7 +228,7 @@ public class ConcreteProduct2 implements Product { } ``` -以下的 Client 类中包含了实例化的代码,这是一种错误的实现,如果在客户类中存在实例化代码,就需要将代码放到简单工厂中。 +以下的 Client 类包含了实例化的代码,这是一种错误的实现。如果在客户类中存在这种实例化代码,就需要考虑将代码放到简单工厂中。 ```java public class Client { @@ -988,6 +988,7 @@ public class ConcreteAggregate implements Aggregate { ```java public interface Iterator { + Item next(); boolean hasNext(); @@ -1018,6 +1019,7 @@ public class ConcreteIterator implements Iterator { ```java public class Client { + public static void main(String[] args) { Aggregate aggregate = new ConcreteAggregate(); Iterator iterator = aggregate.createIterator(); @@ -1826,7 +1828,7 @@ No gumball dispensed ### Class Diagram -- Strategy 接口定义了一个算法族,它们都具有 behavior() 方法。 +- Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。 - Context 是使用到该算法族的类,其中的 doSomething() 方法会调用 behavior(),setStrategy(Strategy) 方法可以动态地改变 strategy 对象,也就是说能动态地改变 Context 所使用的算法。

@@ -1867,6 +1869,7 @@ public class Squeak implements QuackBehavior{ ```java public class Duck { + private QuackBehavior quackBehavior; public void performQuack() { @@ -1883,6 +1886,7 @@ public class Duck { ```java public class Client { + public static void main(String[] args) { Duck duck = new Duck(); duck.setQuackBehavior(new Squeak()); @@ -2706,6 +2710,7 @@ public class Mocha extends CondimentDecorator { ```java public class Client { + public static void main(String[] args) { Beverage beverage = new HouseBlend(); beverage = new Mocha(beverage); @@ -2845,6 +2850,7 @@ public class FlyweightFactory { ```java public class Client { + public static void main(String[] args) { FlyweightFactory factory = new FlyweightFactory(); Flyweight flyweight1 = factory.getFlyweight("aa"); From 7ec044276a91bdd6edecdac26a4ac356ab626549 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 1 Sep 2018 17:09:59 +0800 Subject: [PATCH 046/136] auto commit --- notes/计算机操作系统.md | 43 +++++++++++++++++++++++++++-------------- notes/面向对象思想.md | 4 ++-- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 73f67c62..44f8eb35 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -15,6 +15,10 @@ * [三、死锁](#三死锁) * [死锁的必要条件](#死锁的必要条件) * [死锁的处理方法](#死锁的处理方法) + * [鸵鸟策略](#鸵鸟策略) + * [死锁检测与死锁恢复](#死锁检测与死锁恢复) + * [死锁预防](#死锁预防) + * [死锁避免](#死锁避免) * [四、内存管理](#四内存管理) * [虚拟内存](#虚拟内存) * [分页系统地址映射](#分页系统地址映射) @@ -603,19 +607,28 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 ## 死锁的处理方法 -### 1. 鸵鸟策略 +主要有以下四种方法: + +- 鸵鸟策略; +- 死锁检测与死锁恢复 +- 死锁预防 +- 死锁避免 + +## 鸵鸟策略 把头埋在沙子里,假装根本没发生问题。 -因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。 +因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。 + +当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。 大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。 -### 2. 死锁检测与死锁恢复 +## 死锁检测与死锁恢复 不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。 -(一)每种类型一个资源的死锁检测 +### 1. 每种类型一个资源的死锁检测

@@ -625,7 +638,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。 -(二)每种类型多个资源的死锁检测 +### 2. 每种类型多个资源的死锁检测

@@ -646,35 +659,35 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。 3. 如果没有这样一个进程,算法终止。 -(三)死锁恢复 +### 3. 死锁恢复 - 利用抢占恢复 - 利用回滚恢复 - 通过杀死进程恢复 -### 3. 死锁预防 +## 死锁预防 在程序运行之前预防发生死锁。 -(一)破坏互斥条件 +### 1. 破坏互斥条件 例如假脱机打印机技术允许若干个进程同时输出,唯一真正请求物理打印机的进程是打印机守护进程。 -(二)破坏占有和等待条件 +### 2. 破坏占有和等待条件 一种实现方式是规定所有进程在开始执行前请求所需要的全部资源。 -(三)破坏不可抢占条件 +### 3. 破坏不可抢占条件 -(四)破坏环路等待 +### 4. 破坏环路等待 给资源统一编号,进程只能按编号顺序来请求资源。 -### 4. 死锁避免 +## 死锁避免 在程序运行时避免发生死锁。 -(一)安全状态 +### 1. 安全状态

@@ -684,7 +697,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 安全状态的检测与死锁的检测类似,因为安全状态必须要求不能发生死锁。下面的银行家算法与死锁检测算法非常类似,可以结合着做参考对比。 -(二)单个资源的银行家算法 +### 2. 单个资源的银行家算法 一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。 @@ -692,7 +705,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。 -(三)多个资源的银行家算法 +### 3. 多个资源的银行家算法

diff --git a/notes/面向对象思想.md b/notes/面向对象思想.md index 87b3b033..667ba3e1 100644 --- a/notes/面向对象思想.md +++ b/notes/面向对象思想.md @@ -235,9 +235,9 @@ School "1" - "n" Student 和关联关系不同的是,依赖关系是在运行过程中起作用的。A 类和 B 类是依赖关系主要有三种形式: -- A 类是 B 类中的(某中方法的)局部变量; +- A 类是 B 类方法的局部变量; - A 类是 B 类方法当中的一个参数; -- A 类向 B 类发送消息,从而影响 B 类发生变化; +- A 类向 B 类发送消息,从而影响 B 类发生变化。

From b0b9fbe8c6bdad302ecf83055187d4e40c128686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Sat, 1 Sep 2018 17:23:28 +0800 Subject: [PATCH 047/136] Update README.md --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 27edaf24..6a301d34 100644 --- a/README.md +++ b/README.md @@ -165,11 +165,13 @@ #### About -这个仓库是笔者的一个学习笔记,主要总结一些比较重要的知识点,希望对大家有所帮助。 +本仓库主要是根据计算机经典书籍以及官方技术文档进行总结的学习笔记,希望对大家有所帮助。 -笔记不是从网上到处复制粘贴拼凑而来,虽然有少部分内容会直接引入书上原文或者官方技术文档的原文,但是没有直接摘抄其他人的博客文章,只做了参考,参考的文章会在最后给出链接。 +学习笔记不是从网上到处拼凑而来,除了少部分引用书上和技术文档的原文,其余都是笔者的原创。在您引用本仓库内容或者对内容进行修改演绎时,请遵循文末的开源协议,谢谢。 -[BOOKLIST](https://github.com/CyC2018/Interview-Notebook/blob/master/BOOKLIST.md),这个书单是笔者至今看的一些比较好的技术书籍,虽然没有全都看完,但每本书多多少少都看了一部分。 +#### BookList + +本仓库参考的书目:[BOOKLIST](https://github.com/CyC2018/Interview-Notebook/blob/master/BOOKLIST.md)。 #### How To Contribute From e7af66ace189bf1defbfc85ce7641a44d3099ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Sat, 1 Sep 2018 17:24:36 +0800 Subject: [PATCH 048/136] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a301d34..7ee0bf57 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ #### How To Contribute -笔记内容是笔者一个字一个字打上去的,难免会有一些笔误,如果发现笔误可直接在相应文档进行编辑修改。 +笔记内容是笔者一个字一个字打上去的,难免会有一些笔误,如果发现笔误可直接对相应文档进行编辑修改。 如果想要提交一个仓库现在还没有的全新内容,可以先将相应的文档放到 other 目录下。 From 9308a2a496e78f6be405c8105659439cc4aac99a Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 1 Sep 2018 17:34:48 +0800 Subject: [PATCH 049/136] auto commit --- notes/计算机操作系统.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 44f8eb35..4125d86d 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -167,19 +167,19 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H ### 3. 区别 -(一)拥有资源 +Ⅰ 拥有资源 进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。 -(二)调度 +Ⅱ 调度 线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。 -(三)系统开销 +Ⅲ 系统开销 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。 -(四)通信方面 +Ⅳ 通信方面 进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。 From 39965a71dbf1c7d6d0773001e3ca0b4103f0d9bd Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 2 Sep 2018 10:59:51 +0800 Subject: [PATCH 050/136] auto commit --- notes/Linux.md | 34 +++++++++++++++++----------------- notes/剑指 offer 题解.md | 2 +- notes/系统设计基础.md | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/notes/Linux.md b/notes/Linux.md index 4ba647a7..5e9528e6 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -45,7 +45,7 @@ * [变量操作](#变量操作) * [指令搜索顺序](#指令搜索顺序) * [数据流重定向](#数据流重定向) -* [八、管线指令](#八管线指令) +* [八、管道指令](#八管道指令) * [提取指令](#提取指令) * [排序指令](#排序指令) * [双向输出重定向](#双向输出重定向) @@ -823,7 +823,7 @@ $ echo ${array[1]} - 以绝对或相对路径来执行指令,例如 /bin/ls 或者 ./ls ; - 由别名找到该指令来执行; -- 由 Bash 内建的指令来执行; +- 由 Bash 内置的指令来执行; - 按 \$PATH 变量指定的搜索路径的顺序找到第一个指令来执行。 ## 数据流重定向 @@ -846,11 +846,11 @@ $ echo ${array[1]} $ find /home -name .bashrc > list 2>&1 ``` -# 八、管线指令 +# 八、管道指令 -管线是将一个命令的标准输出作为另一个命令的标准输入,在数据需要经过多个步骤的处理之后才能得到我们想要的内容时就可以使用管线。 +管道是将一个命令的标准输出作为另一个命令的标准输入,在数据需要经过多个步骤的处理之后才能得到我们想要的内容时就可以使用管道。 -在命令之间使用 | 分隔各个管线命令。 +在命令之间使用 | 分隔各个管道命令。 ```bash $ ls -al /etc | less @@ -1053,7 +1053,7 @@ $ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt) awk 每次处理一行,处理的最小单位是字段,每个字段的命名方式为:\$n,n 为字段号,从 1 开始,\$0 表示一整行。 -示例:取出登录用户的用户名和 IP +示例:取出最近五个登录用户的用户名和 IP ```html $ last -n 5 @@ -1128,17 +1128,7 @@ dmtsai lines: 5 columns: 9 # ps aux | grep threadx ``` -### 2. top - -实时显示进程信息 - -示例:两秒钟刷新一次 - -```sh -# top -d 2 -``` - -### 3. pstree +### 2. pstree 查看进程树 @@ -1148,6 +1138,16 @@ dmtsai lines: 5 columns: 9 # pstree -A ``` +### 3. top + +实时显示进程信息 + +示例:两秒钟刷新一次 + +```sh +# top -d 2 +``` + ### 4. netstat 查看占用端口的进程 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 63cf170e..af4c1842 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -2244,7 +2244,7 @@ public int GetUglyNumber_Solution(int N) { ## 题目描述 -在一个字符串 中找到第一个只出现一次的字符,并返回它的位置。 +在一个字符串中找到第一个只出现一次的字符,并返回它的位置。 ## 解题思路 diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index b6a3ddf5..4a961140 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -13,7 +13,7 @@ ### 1. 响应时间 -指从某个请求从发出到接收到响应消耗的时间。 +指某个请求从发出到接收到响应消耗的时间。 在对响应时间进行测试时,通常采用重复请求方式,然后计算平均响应时间。 From 6ea965a9ef36fb877ec4b392b0ad16f2b20907e8 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 2 Sep 2018 22:31:20 +0800 Subject: [PATCH 051/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 16 ++++++++++++++++ notes/MySQL.md | 10 +++++----- 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 notes/CyC 学习交流群 问题汇总.md diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md new file mode 100644 index 00000000..806d48d0 --- /dev/null +++ b/notes/CyC 学习交流群 问题汇总.md @@ -0,0 +1,16 @@ + +* [0. 进程内存空间中,堆和栈的区别](#0-进程内存空间中,堆和栈的区别) + + + +# 0. 进程内存空间中,堆和栈的区别 + +> C++ + +堆:动态、malloc()、new、链式分配、向上生长;栈:函数调用、编译器分配回收、向下生长。 + +https://www.cnblogs.com/sunziying/p/6510030.html + +By @CyC + +--- diff --git a/notes/MySQL.md b/notes/MySQL.md index f115ce92..3922b8a6 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -22,7 +22,7 @@ * [水平切分](#水平切分) * [垂直切分](#垂直切分) * [Sharding 策略](#sharding-策略) - * [Sharding 存在的问题及解决方案](#sharding-存在的问题及解决方案) + * [Sharding 存在的问题](#sharding-存在的问题) * [六、复制](#六复制) * [主从复制](#主从复制) * [读写分离](#读写分离) @@ -366,19 +366,19 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 - 范围:可以是 ID 范围也可以是时间范围; - 映射表:使用单独的一个数据库来存储映射关系。 -## Sharding 存在的问题及解决方案 +## Sharding 存在的问题 ### 1. 事务问题 使用分布式事务来解决,比如 XA 接口。 -### 2. JOIN +### 2. 连接 -可以将原来的 JOIN 分解成多个单表 JOIN 查询,然后在用户程序中进行 JOIN。 +可以将原来的连接分解成多个单表连接查询,然后在用户程序中进行连接。 ### 3. ID 唯一性 -- 使用全局唯一 ID:GUID +- 使用全局唯一 ID(GUID) - 为每个分片指定一个 ID 范围 - 分布式 ID 生成器 (如 Twitter 的 Snowflake 算法) From 9e3ae3e8e6ee7b3e565dec49dc907f257991d38b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 3 Sep 2018 10:36:55 +0800 Subject: [PATCH 052/136] auto commit --- notes/MySQL.md | 10 +++++----- notes/剑指 offer 题解.md | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/notes/MySQL.md b/notes/MySQL.md index f115ce92..3922b8a6 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -22,7 +22,7 @@ * [水平切分](#水平切分) * [垂直切分](#垂直切分) * [Sharding 策略](#sharding-策略) - * [Sharding 存在的问题及解决方案](#sharding-存在的问题及解决方案) + * [Sharding 存在的问题](#sharding-存在的问题) * [六、复制](#六复制) * [主从复制](#主从复制) * [读写分离](#读写分离) @@ -366,19 +366,19 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 - 范围:可以是 ID 范围也可以是时间范围; - 映射表:使用单独的一个数据库来存储映射关系。 -## Sharding 存在的问题及解决方案 +## Sharding 存在的问题 ### 1. 事务问题 使用分布式事务来解决,比如 XA 接口。 -### 2. JOIN +### 2. 连接 -可以将原来的 JOIN 分解成多个单表 JOIN 查询,然后在用户程序中进行 JOIN。 +可以将原来的连接分解成多个单表连接查询,然后在用户程序中进行连接。 ### 3. ID 唯一性 -- 使用全局唯一 ID:GUID +- 使用全局唯一 ID(GUID) - 为每个分片指定一个 ID 范围 - 分布式 ID 生成器 (如 Twitter 的 Snowflake 算法) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index af4c1842..9d3ada1a 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1578,7 +1578,7 @@ private boolean verify(int[] sequence, int first, int last) { int cutIndex = first; while (cutIndex < last && sequence[cutIndex] <= rootVal) cutIndex++; - for (int i = cutIndex + 1; i < last; i++) + for (int i = cutIndex; i < last; i++) if (sequence[i] < rootVal) return false; return verify(sequence, first, cutIndex - 1) && verify(sequence, cutIndex, last - 1); From 137710c64535da5a13ed4f2aa6429a1133356d5a Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 3 Sep 2018 22:34:58 +0800 Subject: [PATCH 053/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 16 ---------------- notes/消息队列.md | 2 +- notes/缓存.md | 17 ++++++++++++----- 3 files changed, 13 insertions(+), 22 deletions(-) delete mode 100644 notes/CyC 学习交流群 问题汇总.md diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md deleted file mode 100644 index 806d48d0..00000000 --- a/notes/CyC 学习交流群 问题汇总.md +++ /dev/null @@ -1,16 +0,0 @@ - -* [0. 进程内存空间中,堆和栈的区别](#0-进程内存空间中,堆和栈的区别) - - - -# 0. 进程内存空间中,堆和栈的区别 - -> C++ - -堆:动态、malloc()、new、链式分配、向上生长;栈:函数调用、编译器分配回收、向下生长。 - -https://www.cnblogs.com/sunziying/p/6510030.html - -By @CyC - ---- diff --git a/notes/消息队列.md b/notes/消息队列.md index bc80894d..2226de74 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -70,7 +70,7 @@ 接收端能够从消息队列成功消费一次消息。 -实现方法: +两种实现方法: - 保证接收端处理消息的业务逻辑具有幂等性:只要具有幂等性,那么消费多少次消息,最后处理的结果都是一样的。 - 保证消息具有唯一编号,并使用一张日志表来记录已经消费的消息编号。 diff --git a/notes/缓存.md b/notes/缓存.md index 26d96be1..771c5f6a 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -58,6 +58,7 @@ public class LRU implements Iterable { } } + public LRU(int maxSize) { this.maxSize = maxSize; @@ -70,6 +71,7 @@ public class LRU implements Iterable { tail.pre = head; } + public V get(K key) { if (!map.containsKey(key)) { @@ -83,6 +85,7 @@ public class LRU implements Iterable { return node.v; } + public void put(K key, V value) { if (map.containsKey(key)) { @@ -100,30 +103,34 @@ public class LRU implements Iterable { } } + private void unlink(Node node) { Node pre = node.pre; - node.pre = node.next; - node.next = pre; + Node next = node.next; + pre.next = next; + next.pre = pre; } + private void appendHead(Node node) { node.next = head.next; + node.pre = head; head.next = node; } + private Node removeTail() { Node node = tail.pre; - node.pre = tail; + tail.pre = node.pre; return node; } + @Override public Iterator iterator() { return new Iterator() { - private Node cur = head.next; - @Override public boolean hasNext() { return cur != tail; From d44274c7cc898762bc4b6e57650cefd62658ccf5 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 3 Sep 2018 22:37:06 +0800 Subject: [PATCH 054/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 notes/CyC 学习交流群 问题汇总.md diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md new file mode 100644 index 00000000..806d48d0 --- /dev/null +++ b/notes/CyC 学习交流群 问题汇总.md @@ -0,0 +1,16 @@ + +* [0. 进程内存空间中,堆和栈的区别](#0-进程内存空间中,堆和栈的区别) + + + +# 0. 进程内存空间中,堆和栈的区别 + +> C++ + +堆:动态、malloc()、new、链式分配、向上生长;栈:函数调用、编译器分配回收、向下生长。 + +https://www.cnblogs.com/sunziying/p/6510030.html + +By @CyC + +--- From 13f44993d874a5e205dae479c0fdf5073a81622b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 3 Sep 2018 22:47:07 +0800 Subject: [PATCH 055/136] auto commit --- notes/缓存.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/缓存.md b/notes/缓存.md index 771c5f6a..8f7449bf 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -169,7 +169,7 @@ public class LRU implements Iterable { 使用 Redis、Memcache 等分布式缓存将数据缓存在分布式缓存系统中。 -相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 +相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现难度和性能开销上都非常大。 ## 数据库缓存 @@ -248,7 +248,7 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了

-一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它后一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。 +一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它前一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。

From 93090ab6a7668642100ca4a2ac60a6919fda6ff4 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 4 Sep 2018 00:04:01 +0800 Subject: [PATCH 056/136] auto commit --- notes/分布式.md | 2 +- notes/攻击技术.md | 40 ++++++++-------------------------------- notes/集群.md | 7 +++---- 3 files changed, 12 insertions(+), 37 deletions(-) diff --git a/notes/分布式.md b/notes/分布式.md index 113837ce..a39ae35e 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -167,7 +167,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操,请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 ## 分区容忍性 diff --git a/notes/攻击技术.md b/notes/攻击技术.md index 46dd4616..31eeaaa4 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -13,6 +13,8 @@ 跨站脚本攻击(Cross-Site Scripting, XSS),可以将代码注入到用户浏览的网页上,这种代码包括 HTML 和 JavaScript。 +## 攻击原理 + 例如有一个论坛网站,攻击者可以在上面发布以下内容: ```html @@ -43,40 +45,23 @@ 例如将 `<` 转义为 `<`,将 `>` 转义为 `>`,从而避免 HTML 和 Jascript 代码的运行。 -## 富文本编辑器 - 富文本编辑器允许用户输入 HTML 代码,就不能简单地将 `<` 等字符进行过滤了,极大地提高了 XSS 攻击的可能性。 富文本编辑器通常采用 XSS filter 来防范 XSS 攻击,通过定义一些标签白名单或者黑名单,从而不允许有攻击性的 HTML 代码的输入。 以下例子中,form 和 script 等标签都被转义,而 h 和 p 等标签将会保留。 -> [XSS 过滤在线测试](http://jsxss.com/zh/try.html) - ```html

XSS Demo

-

-Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist. -

+

123

-
hello
-

- http -

- -

Features:

-
    -
  • Specifies HTML tags and their attributes allowed with whitelist
  • -
  • Handle any tags or attributes using custom function
  • -
- @@ -85,32 +70,21 @@ alert(/xss/); ```html

XSS Demo

-

-Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist. -

+

123

<form> <input type="text" name="q" value="test"> - <button id="submit">Submit</button> </form>
hello
-

- http -

- -

Features:

-
    -
  • Specifies HTML tags and their attributes allowed with whitelist
  • -
  • Handle any tags or attributes using custom function
  • -
- <script type="text/javascript"> alert(/xss/); </script> ``` +> [XSS 过滤在线测试](http://jsxss.com/zh/try.html) + # 二、跨站请求伪造 ## 概念 @@ -119,6 +93,8 @@ alert(/xss/); XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户浏览器的信任。 +## 攻击原理 + 假如一家银行用以执行转账操作的 URL 地址如下: ``` diff --git a/notes/集群.md b/notes/集群.md index 338ddcb4..111495c3 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -18,12 +18,12 @@ 负载均衡器可以用来实现高可用以及伸缩性: - 高可用:当某个节点故障时,负载均衡器会将用户请求转发到另外的节点上,从而保证所有服务持续可用; -- 伸缩性:可以很容易地添加移除节点。 +- 伸缩性:根据系统整体负载情况,可以很容易地添加移除节点。 负载均衡运行过程包含两个部分: -1. 根据负载均衡算法得到请求转发的节点; -2. 将请求进行转发。 +1. 根据负载均衡算法得到转发的节点; +2. 进行转发。 ## 负载均衡算法 @@ -205,4 +205,3 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - [Session Management using Spring Session with JDBC DataStore](https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/) - From 1cdc78e44ac498bbe952a15a2cb5ea1b040c3a5f Mon Sep 17 00:00:00 2001 From: harleyzhao Date: Wed, 5 Sep 2018 11:31:40 +0800 Subject: [PATCH 057/136] =?UTF-8?q?add=20=E7=AE=97=E6=B3=95=E5=92=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Interview-Notebook | 1 + other/算法与数据结构.md | 158 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 160000 Interview-Notebook create mode 100644 other/算法与数据结构.md diff --git a/Interview-Notebook b/Interview-Notebook new file mode 160000 index 00000000..3e35079c --- /dev/null +++ b/Interview-Notebook @@ -0,0 +1 @@ +Subproject commit 3e35079cf9b79b8cc1d577d886aa6abc58793600 diff --git a/other/算法与数据结构.md b/other/算法与数据结构.md new file mode 100644 index 00000000..3f0362f6 --- /dev/null +++ b/other/算法与数据结构.md @@ -0,0 +1,158 @@ +# Algorithm +leetcode/lintcode上的算法题 + +**关于问题的答案和解体的思路,可以移步我的github: https://github.com/zhaozhengcoder/Algorithm** + +### About + + 这个仓库最初的想法是把lintcode/lintocde上面的算法题目整理一下,因为很多题目太多了显得太乱了,就不继续在GitHub上面写了,以前写的一部分移到我的博客上面了。 + GitHub上面打算整理一些比较典型 或者是 自己思考过的觉得很好的问题。 + + + 在博客上面开了两个专栏 + + 1. 数据结构/算法导论 : + https://www.jianshu.com/nb/12397278 + + 2. OJ练习题 : + https://www.jianshu.com/nb/9973135 + + 推荐两篇自己对 递归搜索和动态规划 的理解的blog : + + 1. https://www.jianshu.com/p/5eb4da919efe + + 2. https://www.jianshu.com/p/6b3a2304f63f + + + +### 题目的索引 + GITHUB上面打算整理一些比较典型 或者是 自己思考过的觉得很好的问题。 + + 1.从数据结构的角度索引 : + + a. 数组 + + 两数之和 + + 连续最大子数组 + + 乘积最大子数组 + + 买卖股票的最佳时机1,2,3 + + 买卖股票的最佳时机1:寻找数组里面的最大上升子序列 + 买卖股票的最佳时机2:寻找数组里面所有的上升子序列 + 买卖股票的最佳时机3:寻找数组里面两个不重合的上升子序列,并且使他们的和最大 to-do + + 区间合并(将有交集的区间合并) + + 寻找缺失的数 + + 1. 一个顺序的数组[1,2,3,5,6],缺少了一个数字,如何找到它? + + 2. 一个arr的数组,只有一个数字出现了一次,其他都出现了两次,如何找到它? + + 数组的近似划分(将一个数组分成两个,但是差最小) + + 数组里面第k大的数 + + 跳跃游戏1,2 + + 跳跃游戏1: + 给出一个非负整数数组,你最初定位在数组的第一个位置, + 数组中的每个元素代表你在那个位置可以跳跃的最大长度, + 返回 是否能到达数组的最后一个位置 + + 跳跃游戏2: + 给出一个非负整数数组,你最初定位在数组的第一个位置, + 数组中的每个元素代表你在那个位置可以跳跃的最大长度,    + 返回 使用最少的跳跃次数到达数组的最后一个位置 + + a+. 二维矩阵 + + 顺时针打印二维矩阵 + + 给出一个二维矩阵,找到一个路径(从某个左上角到某个角右下)使这条路径的值最大 + + b. 链表 + + c. 字符串 + + 最长公共子序列(并不是连续的) + + 最长回文子串 + + d. 二叉树 + + 返回一个平衡二叉树的第k大的节点 + + 二叉树的最低公共祖先 + + 非递归遍历二叉树 + + e. 图 + + 最短路径 + + 深度/广度优先遍历 + + 2. 从算法的角度建立索引 : + + a. 递归搜索问题 + + N后问题 + + 全排列 + + 组合问题1,2 + + b. 动态规划 + + 背包问题1,2 + + 数组的近似划分(将一个数组分成两个,但是差最小) + + 跳跃游戏1,2 + + 给出一个二维矩阵,找到一个路径(从某个左上角到某个角右下)使这条路径的值最大 + + + 3. 常用 + + a. 排列/组合 + + b. 深度优先遍历 + + c. 最短路径 + + 4. 智力题(算法本身很简单,就是想不到的那种) + + 最多有多少个点在同一条直线上 + + +### Others + + 1. 类似于系统设计的题目 + + 带最小值的栈/队列 + + url长链接转短链接 + + 2. 解决特定问题 + + 并查集 + + 布隆过滤器 + + + +如果你对机器学习的算法感兴趣,欢迎共同讨论: + +https://github.com/zhaozhengcoder/Machine-Learning + + +### Flag + +刷到200题吧~ + +![](1.PNG) \ No newline at end of file From 8156c42eec21885ed4db5a19b4d93ef373a7b441 Mon Sep 17 00:00:00 2001 From: harleyzhao Date: Wed, 5 Sep 2018 11:34:33 +0800 Subject: [PATCH 058/136] add --- other/算法与数据结构.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/other/算法与数据结构.md b/other/算法与数据结构.md index 3f0362f6..d1e4ddf3 100644 --- a/other/算法与数据结构.md +++ b/other/算法与数据结构.md @@ -1,7 +1,7 @@ # Algorithm leetcode/lintcode上的算法题 -**关于问题的答案和解体的思路,可以移步我的github: https://github.com/zhaozhengcoder/Algorithm** +**关于问题的答案和解体的思路,可以移步 : https://github.com/zhaozhengcoder/Algorithm** ### About @@ -149,10 +149,3 @@ leetcode/lintcode上的算法题 如果你对机器学习的算法感兴趣,欢迎共同讨论: https://github.com/zhaozhengcoder/Machine-Learning - - -### Flag - -刷到200题吧~ - -![](1.PNG) \ No newline at end of file From 5fe72c31d8bf627ebb4776d7ec72af4ce832d2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Wed, 5 Sep 2018 16:04:01 +0800 Subject: [PATCH 059/136] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 7ee0bf57..ded19a67 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ - - ### :pencil2: 算法 - [剑指 Offer 题解](https://github.com/CyC2018/InnterviewNotes/blob/master/notes/剑指%20offer%20题解.md) From 9aebc4660fd0cd02d43f03e81d16178fbd00447b Mon Sep 17 00:00:00 2001 From: peierlong Date: Wed, 5 Sep 2018 16:59:23 +0800 Subject: [PATCH 060/136] =?UTF-8?q?=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=9E=9A=E4=B8=BE=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/设计模式.md | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/notes/设计模式.md b/notes/设计模式.md index 9d9ab38f..b893599c 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -179,6 +179,52 @@ public class Singleton { 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 +#### Ⅵ 枚举实现 + +使用单元素的枚举类型来实现单例模式,相对于常规的单例模式,枚举实现的单例天生具有防止反射实例化对象和反序列化产生实例化对象,而且代码更加简洁,非常适合单例模式场景下使用。以下是枚举单例模式的实现。 + +```java + +public enum EnumSingleton { + INSTANCE; //单元素枚举实现单例 + + private String objName; + + public String getObjName() { + return objName; + } + + public void setObjName(String objName) { + this.objName = objName; + } + + public static void main(String[] args) { + // 单例测试 + EnumSingleton firstSingleton = EnumSingleton.INSTANCE; + firstSingleton.setObjName("firstName"); + System.out.println(firstSingleton.getObjName()); + + EnumSingleton secondSingleton = EnumSingleton.INSTANCE; + secondSingleton.setObjName("secondName"); + System.out.println(firstSingleton.getObjName()); + System.out.println(secondSingleton.getObjName()); + + // 反射获取实例测试 + try { + Constructor constructor = EnumSingleton.class.getDeclaredConstructor(); + constructor.setAccessible(true); + EnumSingleton enumSingleton = constructor.newInstance(); + System.out.println(enumSingleton.getObjName()); + } catch (Exception e) { + e.printStackTrace(); + } + + } +} + +``` + + ### Examples - Logger Classes @@ -2990,3 +3036,5 @@ public class ImageViewer { - [Design Patterns](http://www.oodesign.com/) - [Design patterns implemented in Java](http://java-design-patterns.com/) - [The breakdown of design patterns in JDK](http://www.programering.com/a/MTNxAzMwATY.html) + + From a015b110387eb4a183fac7dc9526de6cd9e316b3 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 5 Sep 2018 17:22:45 +0800 Subject: [PATCH 061/136] auto commit --- notes/Java IO.md | 3 +++ notes/Java 基础.md | 11 ++++++----- notes/Java 虚拟机.md | 4 ++-- notes/剑指 offer 题解.md | 3 ++- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index ee23a4bb..acb95b36 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -182,8 +182,10 @@ public static void readFileContent(String filePath) throws IOException { ```java public static void main(String[] args) throws IOException, ClassNotFoundException { + A a1 = new A(123, "abc"); String objectFile = "file/a1"; + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile)); objectOutputStream.writeObject(a1); objectOutputStream.close(); @@ -195,6 +197,7 @@ public static void main(String[] args) throws IOException, ClassNotFoundExceptio } private static class A implements Serializable { + private int x; private String y; diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 5b689cf8..d8f17cef 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -685,26 +685,26 @@ protected void finalize() throws Throwable {} **1. 等价关系** -(一)自反性 +Ⅰ 自反性 ```java x.equals(x); // true ``` -(二)对称性 +Ⅱ 对称性 ```java x.equals(y) == y.equals(x); // true ``` -(三)传递性 +Ⅲ 传递性 ```java if (x.equals(y) && y.equals(z)) x.equals(z); // true; ``` -(四)一致性 +Ⅳ 一致性 多次调用 equals() 方法结果不变 @@ -712,7 +712,7 @@ if (x.equals(y) && y.equals(z)) x.equals(y) == x.equals(y); // true ``` -(五)与 null 的比较 +Ⅴ 与 null 的比较 对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false @@ -741,6 +741,7 @@ System.out.println(x == y); // false ```java public class EqualExample { + private int x; private int y; private int z; diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 333c1418..2ad1527c 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -30,7 +30,7 @@ # 一、运行时数据区域 -

+

## 程序计数器 @@ -40,7 +40,7 @@ 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。 -

+

可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小: diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 9d3ada1a..2c8f2822 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1433,7 +1433,8 @@ public boolean IsPopOrder(int[] pushSequence, int[] popSequence) { Stack stack = new Stack<>(); for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) { stack.push(pushSequence[pushIndex]); - while (popIndex < n && stack.peek() == popSequence[popIndex]) { + while (popIndex < n && !stack.isEmpty() + && stack.peek() == popSequence[popIndex]) { stack.pop(); popIndex++; } From 4fa8a6b8d63306c6435401fc40a30b466f8c1d04 Mon Sep 17 00:00:00 2001 From: Bandi Yugandhar Date: Wed, 5 Sep 2018 21:50:08 +0530 Subject: [PATCH 062/136] =?UTF-8?q?Update=20and=20rename=20notes/=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E6=9C=BA=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md=20to?= =?UTF-8?q?=20=20notes/=E8=AE=A1=E7=AE=97=E6=9C=BA=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 112 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4125d86d..8751d4f8 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -456,6 +456,118 @@ void writer() { up(&data_mutex); } } +``` +The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer). + + + + +```c +int readcount, writecount; //(initial value = 0) +semaphore rmutex, wmutex, readTry, resource; //(initial value = 1) + +//READER +reader() { + + down(&readLock); // reader is trying to enter + down(&rmutex); // lock to increase readcount + readcount++; + if (readcount == 1) + down(&resource); //if you are the first reader then lock the resource + up(&rmutex); //release for other readers + up(&readLock); //Done with trying to access the resource + + +//reading is performed + + + down(&rmutex); //reserve exit section - avoids race condition with readers + readcount--; //indicate you're leaving + if (readcount == 0) //checks if you are last reader leaving + up(&resource); //if last, you must release the locked resource + up(&rmutex); //release exit section for other readers +} + + +//WRITER +writer() { + + down(&wmutex); //reserve entry section for writers - avoids race conditions + writecount++; //report yourself as a writer entering + if (writecount == 1) //checks if you're first writer + down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS + up(&wmutex); //release entry section + + + down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource + //writing is performed + up(&resource); //release file + + + down(&wmutex); //reserve exit section + writecount--; //indicate you're leaving + if (writecount == 0) //checks if you're the last writer + up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading + up(&wmutex); //release exit section +} + +We can observe that every reader is forced to acquire ReadTry lock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadTry lock, it will be released only when there is writer left in the queue. + + +From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. + +int readCount; // init to 0; number of readers currently accessing resource + +// all semaphores initialised to 1 +Semaphore resourceAccess; // controls access (read/write) to the resource +Semaphore readCountAccess; // for syncing changes to shared variable readCount +Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) + +void writer() +{ + down(&serviceQueue); // wait in line to be servicexs + // + down(&resourceAccess); // request exclusive access to resource + // + up(&serviceQueue); // let next in line be serviced + + // + writeResource(); // writing is performed + // + + // + up(&resourceAccess); // release resource access for next reader/writer + // +} + + +void reader() +{ + down(&serviceQueue); // wait in line to be serviced + down(&readCountAccess); // request exclusive access to readCount + // + if (readCount == 0) // if there are no readers already reading: + down(&resourceAccess); // request resource access for readers (writers blocked) + readCount++; // update count of active readers + // + up(&serviceQueue); // let next in line be serviced + up(&readCountAccess); // release access to readCount + + // + readResource(); // reading is performed + // + + down(&readCountAccess); // request exclusive access to readCount + // + readCount--; // update count of active readers + if (readCount == 0) // if there are no readers left: + up(&resourceAccess); // release resource access for all + // + up(&readCountAccess); // release access to readCount +} + + + ``` ### 2. 哲学家进餐问题 From 4ee1497ade4f9d0fb58d2e5fed0417919a13c158 Mon Sep 17 00:00:00 2001 From: Bandi Yugandhar Date: Wed, 5 Sep 2018 22:22:22 +0530 Subject: [PATCH 063/136] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/计算机操作系统.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 8751d4f8..a25daa6f 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -464,10 +464,10 @@ The first case may result Writer to starve. This case favous Writers i.e no writ ```c int readcount, writecount; //(initial value = 0) -semaphore rmutex, wmutex, readTry, resource; //(initial value = 1) +semaphore rmutex, wmutex, readLock, resource; //(initial value = 1) //READER -reader() { +void reader() { down(&readLock); // reader is trying to enter down(&rmutex); // lock to increase readcount @@ -482,7 +482,7 @@ reader() { down(&rmutex); //reserve exit section - avoids race condition with readers - readcount--; //indicate you're leaving + readcount--; //indicate you're leaving if (readcount == 0) //checks if you are last reader leaving up(&resource); //if last, you must release the locked resource up(&rmutex); //release exit section for other readers @@ -490,8 +490,8 @@ reader() { //WRITER -writer() { - +void writer() { + down(&wmutex); //reserve entry section for writers - avoids race conditions writecount++; //report yourself as a writer entering if (writecount == 1) //checks if you're first writer @@ -510,12 +510,14 @@ writer() { up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading up(&wmutex); //release exit section } +``` -We can observe that every reader is forced to acquire ReadTry lock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadTry lock, it will be released only when there is writer left in the queue. +We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue. From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. +```c int readCount; // init to 0; number of readers currently accessing resource // all semaphores initialised to 1 @@ -524,7 +526,7 @@ Semaphore readCountAccess; // for syncing changes to shared variable readCo Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) void writer() -{ +{ down(&serviceQueue); // wait in line to be servicexs // down(&resourceAccess); // request exclusive access to resource @@ -542,7 +544,7 @@ void writer() void reader() -{ +{ down(&serviceQueue); // wait in line to be serviced down(&readCountAccess); // request exclusive access to readCount // From 59fda4cc63932fff2df51645a843cb2110631734 Mon Sep 17 00:00:00 2001 From: duang123 <643363707@qq.com> Date: Thu, 6 Sep 2018 09:21:14 +0800 Subject: [PATCH 064/136] =?UTF-8?q?Update=20=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=B3=BB=E7=BB=9F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 线程间通信也要做好同步,参考自UNP卷2 p4 --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4125d86d..60465ac5 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。 +进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 ## 进程状态的切换 From 6e61d32e20aff1ad8fc477f5e5f0d4a6b06dfaf1 Mon Sep 17 00:00:00 2001 From: zixiao Date: Thu, 6 Sep 2018 11:27:22 +0800 Subject: [PATCH 065/136] the difference of new and malloc --- notes/CyC 学习交流群 问题汇总.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md index 806d48d0..521822b9 100644 --- a/notes/CyC 学习交流群 问题汇总.md +++ b/notes/CyC 学习交流群 问题汇总.md @@ -14,3 +14,21 @@ https://www.cnblogs.com/sunziying/p/6510030.html By @CyC --- +# 1. new 和 malloc 的区别 + +* 属性 +> new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持 +* 参数 +> 使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据类型信息自行计算。malloc则需要显式指出内存的尺寸。 +* 返回类型 +> new操作内存分配成功时,返回的是对象的类型指针,类型严格与对象匹配,无需类型转换,因此new是符合类型安全的操作符。而malloc内存分配成功则是返回void *,需要通过强制类型转换将void *指针转换成我们需要的类型。 +* 分配失败 +> new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败返回NULL。 +* 自定义类型 +> new会先调用operator new 函数,申请足够的内存(通常使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型的指针。delete先调用析构函数,然后调用operator delete函函数释放内存(通常底层使用free实现) +* 重载 +> C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存的起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。malloc不允许重载。 +* 内存区域 +> new 操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是c++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序内存的动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。 +* 能够直观地重新分配内存 +> malloc可以通过relloc进行内存重新分配实现内存扩充。new没有这样的直观配套设施来扩充内存。 From 1365bc4efe3ecb2e2774cbe5b71cba3ce5e810f5 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 18:13:57 +0800 Subject: [PATCH 066/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 18 ---------- notes/MySQL.md | 2 +- notes/计算机操作系统.md | 10 +++--- notes/设计模式.md | 56 +++++--------------------------- 4 files changed, 14 insertions(+), 72 deletions(-) diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md index 521822b9..806d48d0 100644 --- a/notes/CyC 学习交流群 问题汇总.md +++ b/notes/CyC 学习交流群 问题汇总.md @@ -14,21 +14,3 @@ https://www.cnblogs.com/sunziying/p/6510030.html By @CyC --- -# 1. new 和 malloc 的区别 - -* 属性 -> new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持 -* 参数 -> 使用new操作符申请内存分配时无需指定内存块的大小,编译器会根据类型信息自行计算。malloc则需要显式指出内存的尺寸。 -* 返回类型 -> new操作内存分配成功时,返回的是对象的类型指针,类型严格与对象匹配,无需类型转换,因此new是符合类型安全的操作符。而malloc内存分配成功则是返回void *,需要通过强制类型转换将void *指针转换成我们需要的类型。 -* 分配失败 -> new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败返回NULL。 -* 自定义类型 -> new会先调用operator new 函数,申请足够的内存(通常使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型的指针。delete先调用析构函数,然后调用operator delete函函数释放内存(通常底层使用free实现) -* 重载 -> C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存的起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。malloc不允许重载。 -* 内存区域 -> new 操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是c++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序内存的动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。 -* 能够直观地重新分配内存 -> malloc可以通过relloc进行内存重新分配实现内存扩充。new没有这样的直观配套设施来扩充内存。 diff --git a/notes/MySQL.md b/notes/MySQL.md index 3922b8a6..2c5d8935 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -316,7 +316,7 @@ FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示 VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。 -VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。 +在进行存储和检索时,会保留 VARCHAR 末尾的空格,而会删除 CHAR 末尾的空格。 ## 时间和日期 diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 60465ac5..4e3d849f 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -13,8 +13,8 @@ * [经典同步问题](#经典同步问题) * [进程通信](#进程通信) * [三、死锁](#三死锁) - * [死锁的必要条件](#死锁的必要条件) - * [死锁的处理方法](#死锁的处理方法) + * [必要条件](#必要条件) + * [处理方法](#处理方法) * [鸵鸟策略](#鸵鸟策略) * [死锁检测与死锁恢复](#死锁检测与死锁恢复) * [死锁预防](#死锁预防) @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 +进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 ## 进程状态的切换 @@ -596,7 +596,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 # 三、死锁 -## 死锁的必要条件 +## 必要条件

@@ -605,7 +605,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 - 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。 - 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。 -## 死锁的处理方法 +## 处理方法 主要有以下四种方法: diff --git a/notes/设计模式.md b/notes/设计模式.md index b893599c..262fb788 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -175,56 +175,18 @@ public class Singleton { } ``` +#### Ⅵ 枚举实现 + + ```java +public enum Singleton { + INSTANCE; +} + ``` + 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 -#### Ⅵ 枚举实现 - -使用单元素的枚举类型来实现单例模式,相对于常规的单例模式,枚举实现的单例天生具有防止反射实例化对象和反序列化产生实例化对象,而且代码更加简洁,非常适合单例模式场景下使用。以下是枚举单例模式的实现。 - -```java - -public enum EnumSingleton { - INSTANCE; //单元素枚举实现单例 - - private String objName; - - public String getObjName() { - return objName; - } - - public void setObjName(String objName) { - this.objName = objName; - } - - public static void main(String[] args) { - // 单例测试 - EnumSingleton firstSingleton = EnumSingleton.INSTANCE; - firstSingleton.setObjName("firstName"); - System.out.println(firstSingleton.getObjName()); - - EnumSingleton secondSingleton = EnumSingleton.INSTANCE; - secondSingleton.setObjName("secondName"); - System.out.println(firstSingleton.getObjName()); - System.out.println(secondSingleton.getObjName()); - - // 反射获取实例测试 - try { - Constructor constructor = EnumSingleton.class.getDeclaredConstructor(); - constructor.setAccessible(true); - EnumSingleton enumSingleton = constructor.newInstance(); - System.out.println(enumSingleton.getObjName()); - } catch (Exception e) { - e.printStackTrace(); - } - - } -} - -``` - - ### Examples - Logger Classes @@ -3036,5 +2998,3 @@ public class ImageViewer { - [Design Patterns](http://www.oodesign.com/) - [Design patterns implemented in Java](http://java-design-patterns.com/) - [The breakdown of design patterns in JDK](http://www.programering.com/a/MTNxAzMwATY.html) - - From 3c08c153beb648116e72764bd60cd0c3d925a2ec Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 18:24:01 +0800 Subject: [PATCH 067/136] auto commit --- notes/计算机操作系统.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 5eee94b4..e6c462a6 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -457,12 +457,12 @@ void writer() { } } ``` + +以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。 + The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer). - - - -```c +```source-c int readcount, writecount; //(initial value = 0) semaphore rmutex, wmutex, readLock, resource; //(initial value = 1) @@ -482,13 +482,12 @@ void reader() { down(&rmutex); //reserve exit section - avoids race condition with readers - readcount--; //indicate you're leaving + readcount--; //indicate you're leaving if (readcount == 0) //checks if you are last reader leaving up(&resource); //if last, you must release the locked resource up(&rmutex); //release exit section for other readers } - //WRITER void writer() { @@ -514,10 +513,9 @@ void writer() { We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue. - From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. -```c +```source-c int readCount; // init to 0; number of readers currently accessing resource // all semaphores initialised to 1 @@ -532,17 +530,16 @@ void writer() down(&resourceAccess); // request exclusive access to resource //
up(&serviceQueue); // let next in line be serviced - + // writeResource(); // writing is performed // - + // up(&resourceAccess); // release resource access for next reader/writer // } - void reader() { down(&serviceQueue); // wait in line to be serviced @@ -554,11 +551,11 @@ void reader() //
up(&serviceQueue); // let next in line be serviced up(&readCountAccess); // release access to readCount - + // readResource(); // reading is performed // - + down(&readCountAccess); // request exclusive access to readCount // readCount--; // update count of active readers @@ -568,10 +565,9 @@ void reader() up(&readCountAccess); // release access to readCount } - - ``` + ### 2. 哲学家进餐问题

From bd7d42b5166ea8bfa01a77d43a75753f7e28fad3 Mon Sep 17 00:00:00 2001 From: peierlong Date: Thu, 6 Sep 2018 18:26:39 +0800 Subject: [PATCH 068/136] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/设计模式.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index b893599c..febb434a 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -211,14 +211,13 @@ public enum EnumSingleton { // 反射获取实例测试 try { - Constructor constructor = EnumSingleton.class.getDeclaredConstructor(); - constructor.setAccessible(true); - EnumSingleton enumSingleton = constructor.newInstance(); - System.out.println(enumSingleton.getObjName()); + EnumSingleton[] enumConstants = EnumSingleton.class.getEnumConstants(); + for (EnumSingleton enumConstant : enumConstants) { + System.out.println(enumConstant.getObjName()); + } } catch (Exception e) { e.printStackTrace(); } - } } From 941f8e352ccf7ab59d0079efeb3e0940be2a8446 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 18:38:45 +0800 Subject: [PATCH 069/136] auto commit --- notes/设计模式.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index 1d80e151..45cc71f6 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -177,44 +177,46 @@ public class Singleton { #### Ⅵ 枚举实现 -使用单元素的枚举类型来实现单例模式,相对于常规的单例模式,枚举实现的单例天生具有防止反射实例化对象和反序列化产生实例化对象,而且代码更加简洁,非常适合单例模式场景下使用。以下是枚举单例模式的实现。 + ```java +public enum Singleton { -```java - -public enum EnumSingleton { - INSTANCE; //单元素枚举实现单例 + INSTANCE; private String objName; + public String getObjName() { return objName; } + public void setObjName(String objName) { this.objName = objName; } + public static void main(String[] args) { + // 单例测试 - EnumSingleton firstSingleton = EnumSingleton.INSTANCE; + Singleton firstSingleton = Singleton.INSTANCE; firstSingleton.setObjName("firstName"); System.out.println(firstSingleton.getObjName()); - - EnumSingleton secondSingleton = EnumSingleton.INSTANCE; + Singleton secondSingleton = Singleton.INSTANCE; secondSingleton.setObjName("secondName"); System.out.println(firstSingleton.getObjName()); System.out.println(secondSingleton.getObjName()); // 反射获取实例测试 try { - EnumSingleton[] enumConstants = EnumSingleton.class.getEnumConstants(); - for (EnumSingleton enumConstant : enumConstants) { + Singleton[] enumConstants = Singleton.class.getEnumConstants(); + for (Singleton enumConstant : enumConstants) { System.out.println(enumConstant.getObjName()); } } catch (Exception e) { e.printStackTrace(); } } +} ``` 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 From f82b21b49e1d769548684051456bf3c88a7a26a5 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 6 Sep 2018 20:23:48 +0800 Subject: [PATCH 070/136] remove submodule --- Interview-Notebook | 1 - 1 file changed, 1 deletion(-) delete mode 160000 Interview-Notebook diff --git a/Interview-Notebook b/Interview-Notebook deleted file mode 160000 index 3e35079c..00000000 --- a/Interview-Notebook +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3e35079cf9b79b8cc1d577d886aa6abc58793600 From 732420780c0d0044a9305224db9d2631126cb237 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 7 Sep 2018 10:39:03 +0800 Subject: [PATCH 071/136] auto commit --- notes/HTTP.md | 11 +++++------ notes/计算机网络.md | 30 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index aae807e6..d03beaa5 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -25,7 +25,6 @@ * [实体首部字段](#实体首部字段) * [五、具体应用](#五具体应用) * [Cookie](#cookie) - * [6. Secure](#6-secure) * [缓存](#缓存) * [连接管理](#连接管理) * [内容协商](#内容协商) @@ -369,7 +368,7 @@ document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie); ``` -### 6. HttpOnly +### 6. HttpOnly 标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 @@ -377,11 +376,11 @@ console.log(document.cookie); Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly ``` -## 6. Secure +### 7. Secure 标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 -### 7. Session +### 8. Session 除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。 @@ -396,11 +395,11 @@ Session 可以存储在服务器上的文件、数据库或者内存中。也可 应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。 -### 8. 浏览器禁用 Cookie +### 9. 浏览器禁用 Cookie 此时无法使用 Cookie 来保存用户信息,只能使用 Session。除此之外,不能再将 Session ID 存放到 Cookie 中,而是使用 URL 重写技术,将 Session ID 作为 URL 的参数进行传递。 -### 9. Cookie 与 Session 选择 +### 10. Cookie 与 Session 选择 - Cookie 只能存储 ASCII 码字符串,而 Session 则可以存取任何类型的数据,因此在考虑数据复杂性时首选 Session; - Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密; diff --git a/notes/计算机网络.md b/notes/计算机网络.md index 3a08e2a0..fba8a6d0 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -5,7 +5,7 @@ * [主机之间的通信方式](#主机之间的通信方式) * [电路交换与分组交换](#电路交换与分组交换) * [时延](#时延) - * [计算机网络体系结构*](#计算机网络体系结构) + * [计算机网络体系结构](#计算机网络体系结构) * [二、物理层](#二物理层) * [通信方式](#通信方式) * [带通调制](#带通调制) @@ -13,14 +13,14 @@ * [基本问题](#基本问题) * [信道分类](#信道分类) * [信道复用技术](#信道复用技术) - * [CSMA/CD 协议*](#csmacd-协议) + * [CSMA/CD 协议](#csmacd-协议) * [PPP 协议](#ppp-协议) * [MAC 地址](#mac-地址) * [局域网](#局域网) - * [以太网*](#以太网) - * [交换机*](#交换机) + * [以太网](#以太网) + * [交换机](#交换机) * [虚拟局域网](#虚拟局域网) -* [四、网络层*](#四网络层) +* [四、网络层](#四网络层) * [概述](#概述) * [IP 数据报格式](#ip-数据报格式) * [IP 地址编址方式](#ip-地址编址方式) @@ -31,7 +31,7 @@ * [路由器的结构](#路由器的结构) * [路由器分组转发流程](#路由器分组转发流程) * [路由选择协议](#路由选择协议) -* [五、运输层*](#五运输层) +* [五、运输层](#五运输层) * [UDP 和 TCP 的特点](#udp-和-tcp-的特点) * [UDP 首部格式](#udp-首部格式) * [TCP 首部格式](#tcp-首部格式) @@ -121,7 +121,7 @@ 分组在路由器的输入队列和输出队列中排队等待的时间,取决于网络当前的通信量。 -## 计算机网络体系结构* +## 计算机网络体系结构

@@ -129,11 +129,11 @@ - **应用层** :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等。数据单位为报文。 -- **运输层** :提供的是进程间的通用数据传输服务。由于应用层协议很多,定义通用的运输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 +- **运输层** :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的运输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 -- **网络层** :为主机间提供数据传输服务,而运输层协议是为主机中的进程提供服务。网络层把运输层传递下来的报文段或者用户数据报封装成分组。 +- **网络层** :为主机提供数据传输服务。而运输层协议是为主机中的进程提供数据传输服务。网络层把运输层传递下来的报文段或者用户数据报封装成分组。 -- **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供服务。数据链路层把网络层传下来的分组封装成帧。 +- **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。 - **物理层** :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。 @@ -271,7 +271,7 @@ TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中

-## CSMA/CD 协议* +## CSMA/CD 协议 CSMA/CD 表示载波监听多点接入 / 碰撞检测。 @@ -316,7 +316,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-## 以太网* +## 以太网 以太网是一种星型拓扑结构局域网。 @@ -333,7 +333,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-## 交换机* +## 交换机 交换机具有自学习能力,学习的是交换表的内容,交换表中存储着 MAC 地址到接口的映射。 @@ -353,7 +353,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-# 四、网络层* +# 四、网络层 ## 概述 @@ -578,7 +578,7 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。

-# 五、运输层* +# 五、运输层 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。运输层提供了进程间的逻辑通信,运输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个运输层实体之间有一条端到端的逻辑通信信道。 From 187f0bd02326d62cfc4486207acd6123d0566733 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 7 Sep 2018 11:01:47 +0800 Subject: [PATCH 072/136] auto commit --- notes/HTTP.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index d03beaa5..ef6faf87 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -39,7 +39,6 @@ * [认证](#认证) * [完整性保护](#完整性保护) * [HTTPs 的缺点](#https-的缺点) - * [配置 HTTPs](#配置-https) * [七、HTTP/2.0](#七http20) * [HTTP/1.x 缺陷](#http1x-缺陷) * [二进制分帧层](#二进制分帧层) @@ -719,11 +718,6 @@ HTTPs 的报文摘要功能之所以安全,是因为它结合了加密和认 - 因为需要进行加密解密等过程,因此速度会更慢; - 需要支付证书授权的高额费用。 - -## 配置 HTTPs - -[Nginx 配置 HTTPS 服务器](https://aotu.io/notes/2016/08/16/nginx-https/index.html) - # 七、HTTP/2.0 ## HTTP/1.x 缺陷 @@ -848,7 +842,7 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404 # 九、HTTP/1.0 与 HTTP/1.1 的区别 -> 详细内容请见上文 +详细内容请见上文 - HTTP/1.1 默认是长连接 From 24c4864bfb0e55641c2613b07347c84cf41be77f Mon Sep 17 00:00:00 2001 From: Elong Date: Fri, 7 Sep 2018 11:07:21 +0800 Subject: [PATCH 073/136] =?UTF-8?q?Update=20=E8=AE=BE=E8=AE=A1=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 枚举代码风格修正 --- notes/设计模式.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index 45cc71f6..4f561df4 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -657,7 +657,7 @@ public class ConcreteHandler1 extends Handler { @Override protected void handleRequest(Request request) { - if (request.getType() == RequestType.type1) { + if (request.getType() == RequestType.TYPE1) { System.out.println(request.getName() + " is handle by ConcreteHandler1"); return; } @@ -676,7 +676,7 @@ public class ConcreteHandler2 extends Handler{ @Override protected void handleRequest(Request request) { - if (request.getType() == RequestType.type2) { + if (request.getType() == RequestType.TYPE2) { System.out.println(request.getName() + " is handle by ConcreteHandler2"); return; } @@ -709,7 +709,7 @@ public class Request { ```java public enum RequestType { - type1, type2 + TYPE1, TYPE2 } ``` @@ -718,9 +718,9 @@ public class Client { public static void main(String[] args) { Handler handler1 = new ConcreteHandler1(null); Handler handler2 = new ConcreteHandler2(handler1); - Request request1 = new Request(RequestType.type1, "request1"); + Request request1 = new Request(RequestType.TYPE1, "request1"); handler2.handleRequest(request1); - Request request2 = new Request(RequestType.type2, "request2"); + Request request2 = new Request(RequestType.TYPE2, "request2"); handler2.handleRequest(request2); } } From 0fbafacb9bd94d88a1eaf834589b367316e7bc10 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 7 Sep 2018 11:16:10 +0800 Subject: [PATCH 074/136] auto commit --- notes/设计模式.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index 4f561df4..536072c2 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -639,22 +639,27 @@ abc ```java public abstract class Handler { + protected Handler successor; + public Handler(Handler successor) { this.successor = successor; } + protected abstract void handleRequest(Request request); } ``` ```java public class ConcreteHandler1 extends Handler { + public ConcreteHandler1(Handler successor) { super(successor); } + @Override protected void handleRequest(Request request) { if (request.getType() == RequestType.TYPE1) { @@ -669,11 +674,13 @@ public class ConcreteHandler1 extends Handler { ``` ```java -public class ConcreteHandler2 extends Handler{ +public class ConcreteHandler2 extends Handler { + public ConcreteHandler2(Handler successor) { super(successor); } + @Override protected void handleRequest(Request request) { if (request.getType() == RequestType.TYPE2) { @@ -689,22 +696,27 @@ public class ConcreteHandler2 extends Handler{ ```java public class Request { + private RequestType type; private String name; + public Request(RequestType type, String name) { this.type = type; this.name = name; } + public RequestType getType() { return type; } + public String getName() { return name; } } + ``` ```java @@ -715,11 +727,15 @@ public enum RequestType { ```java public class Client { + public static void main(String[] args) { + Handler handler1 = new ConcreteHandler1(null); Handler handler2 = new ConcreteHandler2(handler1); + Request request1 = new Request(RequestType.TYPE1, "request1"); handler2.handleRequest(request1); + Request request2 = new Request(RequestType.TYPE2, "request2"); handler2.handleRequest(request2); } From 0b5be8937f4223682db8603ceefc08f2bb93b89c Mon Sep 17 00:00:00 2001 From: JacobChengZhang Date: Fri, 7 Sep 2018 12:14:31 +0800 Subject: [PATCH 075/136] =?UTF-8?q?fix:=20fix=20several=20typos=20in=20'Ja?= =?UTF-8?q?va=20=E5=AE=B9=E5=99=A8.md'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 容器.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index fd1ee97e..84189928 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -13,7 +13,7 @@ * [HashMap](#hashmap) * [ConcurrentHashMap](#concurrenthashmap) * [LinkedHashMap](#linkedhashmap) - * [WeekHashMap](#weekhashmap) + * [WeakHashMap](#weakhashmap) * [附录](#附录) * [参考资料](#参考资料) @@ -974,7 +974,7 @@ void afterNodeAccess(Node e) { // move node to last ### afterNodeInsertion() -在 put 等操作之后执行,当 removeEldestEntry() 方法返回 ture 时会移除最晚的节点,也就是链表首部节点 first。 +在 put 等操作之后执行,当 removeEldestEntry() 方法返回 true 时会移除最晚的节点,也就是链表首部节点 first。 evict 只有在构建 Map 的时候才为 false,在这里为 true。 @@ -1034,7 +1034,7 @@ public static void main(String[] args) { [3, 1, 4] ``` -## WeekHashMap +## WeakHashMap ### 存储结构 From f6e6808afe95d580d8043d7f912e248e33fbbd5f Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 7 Sep 2018 12:54:04 +0800 Subject: [PATCH 076/136] auto commit --- notes/HTTP.md | 19 ++----- notes/Java IO.md | 3 + notes/Java 基础.md | 11 ++-- notes/Java 虚拟机.md | 4 +- notes/MySQL.md | 2 +- notes/Socket.md | 8 +-- notes/分布式.md | 2 +- notes/剑指 offer 题解.md | 5 +- notes/攻击技术.md | 40 +++---------- notes/消息队列.md | 2 +- notes/缓存.md | 21 ++++--- notes/计算机操作系统.md | 120 +++++++++++++++++++++++++++++++++++++-- notes/计算机网络.md | 30 +++++----- notes/设计模式.md | 72 +++++++++++++++++++++-- notes/集群.md | 7 +-- 15 files changed, 248 insertions(+), 98 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index aae807e6..ef6faf87 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -25,7 +25,6 @@ * [实体首部字段](#实体首部字段) * [五、具体应用](#五具体应用) * [Cookie](#cookie) - * [6. Secure](#6-secure) * [缓存](#缓存) * [连接管理](#连接管理) * [内容协商](#内容协商) @@ -40,7 +39,6 @@ * [认证](#认证) * [完整性保护](#完整性保护) * [HTTPs 的缺点](#https-的缺点) - * [配置 HTTPs](#配置-https) * [七、HTTP/2.0](#七http20) * [HTTP/1.x 缺陷](#http1x-缺陷) * [二进制分帧层](#二进制分帧层) @@ -369,7 +367,7 @@ document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie); ``` -### 6. HttpOnly +### 6. HttpOnly 标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 @@ -377,11 +375,11 @@ console.log(document.cookie); Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly ``` -## 6. Secure +### 7. Secure 标记为 Secure 的 Cookie 只能通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 -### 7. Session +### 8. Session 除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。 @@ -396,11 +394,11 @@ Session 可以存储在服务器上的文件、数据库或者内存中。也可 应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。 -### 8. 浏览器禁用 Cookie +### 9. 浏览器禁用 Cookie 此时无法使用 Cookie 来保存用户信息,只能使用 Session。除此之外,不能再将 Session ID 存放到 Cookie 中,而是使用 URL 重写技术,将 Session ID 作为 URL 的参数进行传递。 -### 9. Cookie 与 Session 选择 +### 10. Cookie 与 Session 选择 - Cookie 只能存储 ASCII 码字符串,而 Session 则可以存取任何类型的数据,因此在考虑数据复杂性时首选 Session; - Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密; @@ -720,11 +718,6 @@ HTTPs 的报文摘要功能之所以安全,是因为它结合了加密和认 - 因为需要进行加密解密等过程,因此速度会更慢; - 需要支付证书授权的高额费用。 - -## 配置 HTTPs - -[Nginx 配置 HTTPS 服务器](https://aotu.io/notes/2016/08/16/nginx-https/index.html) - # 七、HTTP/2.0 ## HTTP/1.x 缺陷 @@ -849,7 +842,7 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404 # 九、HTTP/1.0 与 HTTP/1.1 的区别 -> 详细内容请见上文 +详细内容请见上文 - HTTP/1.1 默认是长连接 diff --git a/notes/Java IO.md b/notes/Java IO.md index ee23a4bb..acb95b36 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -182,8 +182,10 @@ public static void readFileContent(String filePath) throws IOException { ```java public static void main(String[] args) throws IOException, ClassNotFoundException { + A a1 = new A(123, "abc"); String objectFile = "file/a1"; + ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile)); objectOutputStream.writeObject(a1); objectOutputStream.close(); @@ -195,6 +197,7 @@ public static void main(String[] args) throws IOException, ClassNotFoundExceptio } private static class A implements Serializable { + private int x; private String y; diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 5b689cf8..d8f17cef 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -685,26 +685,26 @@ protected void finalize() throws Throwable {} **1. 等价关系** -(一)自反性 +Ⅰ 自反性 ```java x.equals(x); // true ``` -(二)对称性 +Ⅱ 对称性 ```java x.equals(y) == y.equals(x); // true ``` -(三)传递性 +Ⅲ 传递性 ```java if (x.equals(y) && y.equals(z)) x.equals(z); // true; ``` -(四)一致性 +Ⅳ 一致性 多次调用 equals() 方法结果不变 @@ -712,7 +712,7 @@ if (x.equals(y) && y.equals(z)) x.equals(y) == x.equals(y); // true ``` -(五)与 null 的比较 +Ⅴ 与 null 的比较 对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false @@ -741,6 +741,7 @@ System.out.println(x == y); // false ```java public class EqualExample { + private int x; private int y; private int z; diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 333c1418..2ad1527c 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -30,7 +30,7 @@ # 一、运行时数据区域 -

+

## 程序计数器 @@ -40,7 +40,7 @@ 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表、操作数栈、常量池引用等信息。从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程。 -

+

可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小: diff --git a/notes/MySQL.md b/notes/MySQL.md index 3922b8a6..2c5d8935 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -316,7 +316,7 @@ FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示 VARCHAR 这种变长类型能够节省空间,因为只需要存储必要的内容。但是在执行 UPDATE 时可能会使行变得比原来长,当超出一个页所能容纳的大小时,就要执行额外的操作。MyISAM 会将行拆成不同的片段存储,而 InnoDB 则需要分裂页来使行放进页内。 -VARCHAR 会保留字符串末尾的空格,而 CHAR 会删除。 +在进行存储和检索时,会保留 VARCHAR 末尾的空格,而会删除 CHAR 末尾的空格。 ## 时间和日期 diff --git a/notes/Socket.md b/notes/Socket.md index 482bafe6..7cb4fbf0 100644 --- a/notes/Socket.md +++ b/notes/Socket.md @@ -307,14 +307,14 @@ select 可移植性更好,几乎被所有主流平台所支持。 poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。 -需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。 - -需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。 - ### 3. epoll 应用场景 只需要运行在 Linux 平台上,并且有非常大量的描述符需要同时轮询,而且这些连接最好是长连接。 +需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。 + +需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。 + # 参考资料 - Stevens W R, Fenner B, Rudoff A M. UNIX network programming[M]. Addison-Wesley Professional, 2004. diff --git a/notes/分布式.md b/notes/分布式.md index 113837ce..a39ae35e 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -167,7 +167,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。 -在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操,请求总是能够在有限的时间内返回结果。 +在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。 ## 分区容忍性 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index af4c1842..2c8f2822 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1433,7 +1433,8 @@ public boolean IsPopOrder(int[] pushSequence, int[] popSequence) { Stack stack = new Stack<>(); for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) { stack.push(pushSequence[pushIndex]); - while (popIndex < n && stack.peek() == popSequence[popIndex]) { + while (popIndex < n && !stack.isEmpty() + && stack.peek() == popSequence[popIndex]) { stack.pop(); popIndex++; } @@ -1578,7 +1579,7 @@ private boolean verify(int[] sequence, int first, int last) { int cutIndex = first; while (cutIndex < last && sequence[cutIndex] <= rootVal) cutIndex++; - for (int i = cutIndex + 1; i < last; i++) + for (int i = cutIndex; i < last; i++) if (sequence[i] < rootVal) return false; return verify(sequence, first, cutIndex - 1) && verify(sequence, cutIndex, last - 1); diff --git a/notes/攻击技术.md b/notes/攻击技术.md index 46dd4616..31eeaaa4 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -13,6 +13,8 @@ 跨站脚本攻击(Cross-Site Scripting, XSS),可以将代码注入到用户浏览的网页上,这种代码包括 HTML 和 JavaScript。 +## 攻击原理 + 例如有一个论坛网站,攻击者可以在上面发布以下内容: ```html @@ -43,40 +45,23 @@ 例如将 `<` 转义为 `<`,将 `>` 转义为 `>`,从而避免 HTML 和 Jascript 代码的运行。 -## 富文本编辑器 - 富文本编辑器允许用户输入 HTML 代码,就不能简单地将 `<` 等字符进行过滤了,极大地提高了 XSS 攻击的可能性。 富文本编辑器通常采用 XSS filter 来防范 XSS 攻击,通过定义一些标签白名单或者黑名单,从而不允许有攻击性的 HTML 代码的输入。 以下例子中,form 和 script 等标签都被转义,而 h 和 p 等标签将会保留。 -> [XSS 过滤在线测试](http://jsxss.com/zh/try.html) - ```html

XSS Demo

-

-Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist. -

+

123

-
hello
-

- http -

- -

Features:

-
    -
  • Specifies HTML tags and their attributes allowed with whitelist
  • -
  • Handle any tags or attributes using custom function
  • -
- @@ -85,32 +70,21 @@ alert(/xss/); ```html

XSS Demo

-

-Sanitize untrusted HTML (to prevent XSS) with a configuration specified by a Whitelist. -

+

123

<form> <input type="text" name="q" value="test"> - <button id="submit">Submit</button> </form>
hello
-

- http -

- -

Features:

-
    -
  • Specifies HTML tags and their attributes allowed with whitelist
  • -
  • Handle any tags or attributes using custom function
  • -
- <script type="text/javascript"> alert(/xss/); </script> ``` +> [XSS 过滤在线测试](http://jsxss.com/zh/try.html) + # 二、跨站请求伪造 ## 概念 @@ -119,6 +93,8 @@ alert(/xss/); XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户浏览器的信任。 +## 攻击原理 + 假如一家银行用以执行转账操作的 URL 地址如下: ``` diff --git a/notes/消息队列.md b/notes/消息队列.md index bc80894d..2226de74 100644 --- a/notes/消息队列.md +++ b/notes/消息队列.md @@ -70,7 +70,7 @@ 接收端能够从消息队列成功消费一次消息。 -实现方法: +两种实现方法: - 保证接收端处理消息的业务逻辑具有幂等性:只要具有幂等性,那么消费多少次消息,最后处理的结果都是一样的。 - 保证消息具有唯一编号,并使用一张日志表来记录已经消费的消息编号。 diff --git a/notes/缓存.md b/notes/缓存.md index 26d96be1..8f7449bf 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -58,6 +58,7 @@ public class LRU implements Iterable { } } + public LRU(int maxSize) { this.maxSize = maxSize; @@ -70,6 +71,7 @@ public class LRU implements Iterable { tail.pre = head; } + public V get(K key) { if (!map.containsKey(key)) { @@ -83,6 +85,7 @@ public class LRU implements Iterable { return node.v; } + public void put(K key, V value) { if (map.containsKey(key)) { @@ -100,30 +103,34 @@ public class LRU implements Iterable { } } + private void unlink(Node node) { Node pre = node.pre; - node.pre = node.next; - node.next = pre; + Node next = node.next; + pre.next = next; + next.pre = pre; } + private void appendHead(Node node) { node.next = head.next; + node.pre = head; head.next = node; } + private Node removeTail() { Node node = tail.pre; - node.pre = tail; + tail.pre = node.pre; return node; } + @Override public Iterator iterator() { return new Iterator() { - private Node cur = head.next; - @Override public boolean hasNext() { return cur != tail; @@ -162,7 +169,7 @@ public class LRU implements Iterable { 使用 Redis、Memcache 等分布式缓存将数据缓存在分布式缓存系统中。 -相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现和性能开销上都非常大。 +相对于本地缓存来说,分布式缓存单独部署,可以根据需求分配硬件资源。不仅如此,服务器集群都可以访问分布式缓存,而本地缓存需要在服务器集群之间进行同步,实现难度和性能开销上都非常大。 ## 数据库缓存 @@ -241,7 +248,7 @@ Distributed Hash Table(DHT) 是一种哈希分布方式,其目的是为了

-一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它后一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。 +一致性哈希在增加或者删除节点时只会影响到哈希环中相邻的节点,例如下图中新增节点 X,只需要将它前一个节点 C 上的数据重新进行分布即可,对于节点 A、B、D 都没有影响。

diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 4125d86d..e6c462a6 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -13,8 +13,8 @@ * [经典同步问题](#经典同步问题) * [进程通信](#进程通信) * [三、死锁](#三死锁) - * [死锁的必要条件](#死锁的必要条件) - * [死锁的处理方法](#死锁的处理方法) + * [必要条件](#必要条件) + * [处理方法](#处理方法) * [鸵鸟策略](#鸵鸟策略) * [死锁检测与死锁恢复](#死锁检测与死锁恢复) * [死锁预防](#死锁预防) @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信 (IPC) 需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信。 +进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 ## 进程状态的切换 @@ -458,6 +458,116 @@ void writer() { } ``` +以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。 + +The first case may result Writer to starve. This case favous Writers i.e no writer, once added to the queue, shall be kept waiting longer than absolutely necessary(only when there are readers that entered the queue before the writer). + +```source-c +int readcount, writecount; //(initial value = 0) +semaphore rmutex, wmutex, readLock, resource; //(initial value = 1) + +//READER +void reader() { + + down(&readLock); // reader is trying to enter + down(&rmutex); // lock to increase readcount + readcount++; + if (readcount == 1) + down(&resource); //if you are the first reader then lock the resource + up(&rmutex); //release for other readers + up(&readLock); //Done with trying to access the resource + + +//reading is performed + + + down(&rmutex); //reserve exit section - avoids race condition with readers + readcount--; //indicate you're leaving + if (readcount == 0) //checks if you are last reader leaving + up(&resource); //if last, you must release the locked resource + up(&rmutex); //release exit section for other readers +} + +//WRITER +void writer() { + + down(&wmutex); //reserve entry section for writers - avoids race conditions + writecount++; //report yourself as a writer entering + if (writecount == 1) //checks if you're first writer + down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS + up(&wmutex); //release entry section + + + down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource + //writing is performed + up(&resource); //release file + + + down(&wmutex); //reserve exit section + writecount--; //indicate you're leaving + if (writecount == 0) //checks if you're the last writer + up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading + up(&wmutex); //release exit section +} +``` + +We can observe that every reader is forced to acquire ReadLock. On the otherhand, writers doesn’t need to lock individually. Once the first writer locks the ReadLock, it will be released only when there is no writer left in the queue. + +From the both cases we observed that either reader or writer has to starve. Below solutionadds the constraint that no thread shall be allowed to starve; that is, the operation of obtaining a lock on the shared data will always terminate in a bounded amount of time. + +```source-c +int readCount; // init to 0; number of readers currently accessing resource + +// all semaphores initialised to 1 +Semaphore resourceAccess; // controls access (read/write) to the resource +Semaphore readCountAccess; // for syncing changes to shared variable readCount +Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO) + +void writer() +{ + down(&serviceQueue); // wait in line to be servicexs + // + down(&resourceAccess); // request exclusive access to resource + // + up(&serviceQueue); // let next in line be serviced + + // + writeResource(); // writing is performed + // + + // + up(&resourceAccess); // release resource access for next reader/writer + // +} + +void reader() +{ + down(&serviceQueue); // wait in line to be serviced + down(&readCountAccess); // request exclusive access to readCount + // + if (readCount == 0) // if there are no readers already reading: + down(&resourceAccess); // request resource access for readers (writers blocked) + readCount++; // update count of active readers + // + up(&serviceQueue); // let next in line be serviced + up(&readCountAccess); // release access to readCount + + // + readResource(); // reading is performed + // + + down(&readCountAccess); // request exclusive access to readCount + // + readCount--; // update count of active readers + if (readCount == 0) // if there are no readers left: + up(&resourceAccess); // release resource access for all + // + up(&readCountAccess); // release access to readCount +} + +``` + + ### 2. 哲学家进餐问题

@@ -596,7 +706,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 # 三、死锁 -## 死锁的必要条件 +## 必要条件

@@ -605,7 +715,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 - 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。 - 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。 -## 死锁的处理方法 +## 处理方法 主要有以下四种方法: diff --git a/notes/计算机网络.md b/notes/计算机网络.md index 3a08e2a0..fba8a6d0 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -5,7 +5,7 @@ * [主机之间的通信方式](#主机之间的通信方式) * [电路交换与分组交换](#电路交换与分组交换) * [时延](#时延) - * [计算机网络体系结构*](#计算机网络体系结构) + * [计算机网络体系结构](#计算机网络体系结构) * [二、物理层](#二物理层) * [通信方式](#通信方式) * [带通调制](#带通调制) @@ -13,14 +13,14 @@ * [基本问题](#基本问题) * [信道分类](#信道分类) * [信道复用技术](#信道复用技术) - * [CSMA/CD 协议*](#csmacd-协议) + * [CSMA/CD 协议](#csmacd-协议) * [PPP 协议](#ppp-协议) * [MAC 地址](#mac-地址) * [局域网](#局域网) - * [以太网*](#以太网) - * [交换机*](#交换机) + * [以太网](#以太网) + * [交换机](#交换机) * [虚拟局域网](#虚拟局域网) -* [四、网络层*](#四网络层) +* [四、网络层](#四网络层) * [概述](#概述) * [IP 数据报格式](#ip-数据报格式) * [IP 地址编址方式](#ip-地址编址方式) @@ -31,7 +31,7 @@ * [路由器的结构](#路由器的结构) * [路由器分组转发流程](#路由器分组转发流程) * [路由选择协议](#路由选择协议) -* [五、运输层*](#五运输层) +* [五、运输层](#五运输层) * [UDP 和 TCP 的特点](#udp-和-tcp-的特点) * [UDP 首部格式](#udp-首部格式) * [TCP 首部格式](#tcp-首部格式) @@ -121,7 +121,7 @@ 分组在路由器的输入队列和输出队列中排队等待的时间,取决于网络当前的通信量。 -## 计算机网络体系结构* +## 计算机网络体系结构

@@ -129,11 +129,11 @@ - **应用层** :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等。数据单位为报文。 -- **运输层** :提供的是进程间的通用数据传输服务。由于应用层协议很多,定义通用的运输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 +- **运输层** :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的运输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 -- **网络层** :为主机间提供数据传输服务,而运输层协议是为主机中的进程提供服务。网络层把运输层传递下来的报文段或者用户数据报封装成分组。 +- **网络层** :为主机提供数据传输服务。而运输层协议是为主机中的进程提供数据传输服务。网络层把运输层传递下来的报文段或者用户数据报封装成分组。 -- **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供服务。数据链路层把网络层传下来的分组封装成帧。 +- **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。 - **物理层** :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异。 @@ -271,7 +271,7 @@ TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中

-## CSMA/CD 协议* +## CSMA/CD 协议 CSMA/CD 表示载波监听多点接入 / 碰撞检测。 @@ -316,7 +316,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-## 以太网* +## 以太网 以太网是一种星型拓扑结构局域网。 @@ -333,7 +333,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-## 交换机* +## 交换机 交换机具有自学习能力,学习的是交换表的内容,交换表中存储着 MAC 地址到接口的映射。 @@ -353,7 +353,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标

-# 四、网络层* +# 四、网络层 ## 概述 @@ -578,7 +578,7 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。

-# 五、运输层* +# 五、运输层 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。运输层提供了进程间的逻辑通信,运输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个运输层实体之间有一条端到端的逻辑通信信道。 diff --git a/notes/设计模式.md b/notes/设计模式.md index 9d9ab38f..536072c2 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -175,6 +175,50 @@ public class Singleton { } ``` +#### Ⅵ 枚举实现 + + ```java +public enum Singleton { + + INSTANCE; + + private String objName; + + + public String getObjName() { + return objName; + } + + + public void setObjName(String objName) { + this.objName = objName; + } + + + public static void main(String[] args) { + + // 单例测试 + Singleton firstSingleton = Singleton.INSTANCE; + firstSingleton.setObjName("firstName"); + System.out.println(firstSingleton.getObjName()); + Singleton secondSingleton = Singleton.INSTANCE; + secondSingleton.setObjName("secondName"); + System.out.println(firstSingleton.getObjName()); + System.out.println(secondSingleton.getObjName()); + + // 反射获取实例测试 + try { + Singleton[] enumConstants = Singleton.class.getEnumConstants(); + for (Singleton enumConstant : enumConstants) { + System.out.println(enumConstant.getObjName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} + ``` + 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 @@ -595,25 +639,30 @@ abc ```java public abstract class Handler { + protected Handler successor; + public Handler(Handler successor) { this.successor = successor; } + protected abstract void handleRequest(Request request); } ``` ```java public class ConcreteHandler1 extends Handler { + public ConcreteHandler1(Handler successor) { super(successor); } + @Override protected void handleRequest(Request request) { - if (request.getType() == RequestType.type1) { + if (request.getType() == RequestType.TYPE1) { System.out.println(request.getName() + " is handle by ConcreteHandler1"); return; } @@ -625,14 +674,16 @@ public class ConcreteHandler1 extends Handler { ``` ```java -public class ConcreteHandler2 extends Handler{ +public class ConcreteHandler2 extends Handler { + public ConcreteHandler2(Handler successor) { super(successor); } + @Override protected void handleRequest(Request request) { - if (request.getType() == RequestType.type2) { + if (request.getType() == RequestType.TYPE2) { System.out.println(request.getName() + " is handle by ConcreteHandler2"); return; } @@ -645,38 +696,47 @@ public class ConcreteHandler2 extends Handler{ ```java public class Request { + private RequestType type; private String name; + public Request(RequestType type, String name) { this.type = type; this.name = name; } + public RequestType getType() { return type; } + public String getName() { return name; } } + ``` ```java public enum RequestType { - type1, type2 + TYPE1, TYPE2 } ``` ```java public class Client { + public static void main(String[] args) { + Handler handler1 = new ConcreteHandler1(null); Handler handler2 = new ConcreteHandler2(handler1); - Request request1 = new Request(RequestType.type1, "request1"); + + Request request1 = new Request(RequestType.TYPE1, "request1"); handler2.handleRequest(request1); - Request request2 = new Request(RequestType.type2, "request2"); + + Request request2 = new Request(RequestType.TYPE2, "request2"); handler2.handleRequest(request2); } } diff --git a/notes/集群.md b/notes/集群.md index 338ddcb4..111495c3 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -18,12 +18,12 @@ 负载均衡器可以用来实现高可用以及伸缩性: - 高可用:当某个节点故障时,负载均衡器会将用户请求转发到另外的节点上,从而保证所有服务持续可用; -- 伸缩性:可以很容易地添加移除节点。 +- 伸缩性:根据系统整体负载情况,可以很容易地添加移除节点。 负载均衡运行过程包含两个部分: -1. 根据负载均衡算法得到请求转发的节点; -2. 将请求进行转发。 +1. 根据负载均衡算法得到转发的节点; +2. 进行转发。 ## 负载均衡算法 @@ -205,4 +205,3 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 - [Session Management using Spring Session with JDBC DataStore](https://sivalabs.in/2018/02/session-management-using-spring-session-jdbc-datastore/) - From 90440d840d1971478de98e1fea3c8fed393bdad8 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 8 Sep 2018 10:14:41 +0800 Subject: [PATCH 077/136] auto commit --- notes/Java 容器.md | 6 +-- notes/Java 并发.md | 115 +++++++-------------------------------------- notes/Socket.md | 8 ++-- notes/设计模式.md | 4 +- 4 files changed, 27 insertions(+), 106 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index fd1ee97e..84189928 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -13,7 +13,7 @@ * [HashMap](#hashmap) * [ConcurrentHashMap](#concurrenthashmap) * [LinkedHashMap](#linkedhashmap) - * [WeekHashMap](#weekhashmap) + * [WeakHashMap](#weakhashmap) * [附录](#附录) * [参考资料](#参考资料) @@ -974,7 +974,7 @@ void afterNodeAccess(Node e) { // move node to last ### afterNodeInsertion() -在 put 等操作之后执行,当 removeEldestEntry() 方法返回 ture 时会移除最晚的节点,也就是链表首部节点 first。 +在 put 等操作之后执行,当 removeEldestEntry() 方法返回 true 时会移除最晚的节点,也就是链表首部节点 first。 evict 只有在构建 Map 的时候才为 false,在这里为 true。 @@ -1034,7 +1034,7 @@ public static void main(String[] args) { [3, 1, 4] ``` -## WeekHashMap +## WeakHashMap ### 存储结构 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 03aaa9fd..977d85f2 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -44,9 +44,10 @@ * [内存模型三大特性](#内存模型三大特性) * [先行发生原则](#先行发生原则) * [十一、线程安全](#十一线程安全) - * [线程安全定义](#线程安全定义) - * [线程安全分类](#线程安全分类) - * [线程安全的实现方法](#线程安全的实现方法) + * [不可变](#不可变) + * [互斥同步](#互斥同步) + * [非阻塞同步](#非阻塞同步) + * [无同步方案](#无同步方案) * [十二、锁优化](#十二锁优化) * [自旋锁](#自旋锁) * [锁消除](#锁消除) @@ -1274,19 +1275,13 @@ Thread 对象的结束先行发生于 join() 方法返回。 # 十一、线程安全 -## 线程安全定义 +多个线程不管以何种方式访问某个类,并在在主调代码中不需要进行同步,都能表现正确的行为。 -一个类在可以被多个线程安全调用时就是线程安全的。 +线程安全有以下几种实现方式: -## 线程安全分类 +## 不可变 -线程安全不是一个非真即假的命题,可以将共享数据按照安全程度的强弱顺序分成以下五类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。 - -### 1. 不可变 - -不可变(Immutable)的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。只要一个不可变的对象被正确地构建出来,永远也不会看到它在多个线程之中处于不一致的状态。 - -多线程环境下,应当尽量使对象成为不可变,来满足线程安全。 +不可变(Immutable)的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。只要一个不可变的对象被正确地构建出来,永远也不会看到它在多个线程之中处于不一致的状态。多线程环境下,应当尽量使对象成为不可变,来满足线程安全。 不可变的类型: @@ -1321,99 +1316,23 @@ public V put(K key, V value) { } ``` -### 2. 绝对线程安全 - -不管运行时环境如何,调用者都不需要任何额外的同步措施。 - -### 3. 相对线程安全 - -相对线程安全需要保证对这个对象单独的操作是线程安全的,在调用的时候不需要做额外的保障措施。但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。 - -在 Java 语言中,大部分的线程安全类都属于这种类型,例如 Vector、HashTable、Collections 的 synchronizedCollection() 方法包装的集合等。 - -对于下面的代码,如果删除元素的线程删除了 Vector 的一个元素,而获取元素的线程试图访问一个已经被删除的元素,那么就会抛出 ArrayIndexOutOfBoundsException。 - -```Java -public class VectorUnsafeExample { - private static Vector vector = new Vector<>(); - - public static void main(String[] args) { - while (true) { - for (int i = 0; i < 100; i++) { - vector.add(i); - } - ExecutorService executorService = Executors.newCachedThreadPool(); - executorService.execute(() -> { - for (int i = 0; i < vector.size(); i++) { - vector.remove(i); - } - }); - executorService.execute(() -> { - for (int i = 0; i < vector.size(); i++) { - vector.get(i); - } - }); - executorService.shutdown(); - } - } -} -``` - -```html -Exception in thread "Thread-159738" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 3 - at java.util.Vector.remove(Vector.java:831) - at VectorUnsafeExample.lambda$main$0(VectorUnsafeExample.java:14) - at VectorUnsafeExample$$Lambda$1/713338599.run(Unknown Source) - at java.lang.Thread.run(Thread.java:745) -``` - - -如果要保证上面的代码能正确执行下去,就需要对删除元素和获取元素的代码进行同步。 - -```java -executorService.execute(() -> { - synchronized (vector) { - for (int i = 0; i < vector.size(); i++) { - vector.remove(i); - } - } -}); -executorService.execute(() -> { - synchronized (vector) { - for (int i = 0; i < vector.size(); i++) { - vector.get(i); - } - } -}); -``` - -### 4. 线程兼容 - -线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全地使用,我们平常说一个类不是线程安全的,绝大多数时候指的是这一种情况。Java API 中大部分的类都是属于线程兼容的,如与前面的 Vector 和 HashTable 相对应的集合类 ArrayList 和 HashMap 等。 - -### 5. 线程对立 - -线程对立是指无论调用端是否采取了同步措施,都无法在多线程环境中并发使用的代码。由于 Java 语言天生就具备多线程特性,线程对立这种排斥多线程的代码是很少出现的,而且通常都是有害的,应当尽量避免。 - -## 线程安全的实现方法 - -### 1. 互斥同步 +## 互斥同步 synchronized 和 ReentrantLock。 -### 2. 非阻塞同步 +## 非阻塞同步 互斥同步最主要的问题就是线程阻塞和唤醒所带来的性能问题,因此这种同步也称为阻塞同步。 互斥同步属于一种悲观的并发策略,总是认为只要不去做正确的同步措施,那就肯定会出现问题。无论共享数据是否真的会出现竞争,它都要进行加锁(这里讨论的是概念模型,实际上虚拟机会优化掉很大一部分不必要的加锁)、用户态核心态转换、维护锁计数器和检查是否有被阻塞的线程需要唤醒等操作。 -**(一)CAS** +### 1. CAS 随着硬件指令集的发展,我们可以使用基于冲突检测的乐观并发策略:先进行操作,如果没有其它线程争用共享数据,那操作就成功了,否则采取补偿措施(不断地重试,直到成功为止)。这种乐观的并发策略的许多实现都不需要将线程阻塞,因此这种同步操作称为非阻塞同步。 乐观锁需要操作和冲突检测这两个步骤具备原子性,这里就不能再使用互斥同步来保证了,只能靠硬件来完成。硬件支持的原子性操作最典型的是:比较并交换(Compare-and-Swap,CAS)。CAS 指令需要有 3 个操作数,分别是内存地址 V、旧的预期值 A 和新值 B。当执行操作时,只有当 V 的值等于 A,才将 V 的值更新为 B。 -**(二)AtomicInteger** +### 2. AtomicInteger J.U.C 包里面的整数原子类 AtomicInteger 的方法调用了 Unsafe 类的 CAS 操作。 @@ -1450,17 +1369,17 @@ public final int getAndAddInt(Object var1, long var2, int var4) { } ``` -**(三)ABA** +### 3. ABA 如果一个变量初次读取的时候是 A 值,它的值被改成了 B,后来又被改回为 A,那 CAS 操作就会误认为它从来没有被改变过。 J.U.C 包提供了一个带有标记的原子引用类 AtomicStampedReference 来解决这个问题,它可以通过控制变量值的版本来保证 CAS 的正确性。大部分情况下 ABA 问题不会影响程序并发的正确性,如果需要解决 ABA 问题,改用传统的互斥同步可能会比原子类更高效。 -### 3. 无同步方案 +## 无同步方案 要保证线程安全,并不是一定就要进行同步。如果一个方法本来就不涉及共享数据,那它自然就无须任何同步措施去保证正确性。 -**(一)栈封闭** +### 1. 栈封闭 多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在虚拟机栈中,属于线程私有的。 @@ -1491,7 +1410,7 @@ public static void main(String[] args) { 100 ``` -**(二)线程本地存储(Thread Local Storage)** +### 2. 线程本地存储(Thread Local Storage) 如果一段代码中所需要的数据必须与其他代码共享,那就看看这些共享数据的代码是否能保证在同一个线程中执行。如果能保证,我们就可以把共享数据的可见范围限制在同一个线程之内,这样,无须同步也能保证线程之间不出现数据争用的问题。 @@ -1597,7 +1516,7 @@ ThreadLocal 从理论上讲并不是用来解决多线程并发问题的,因 在一些场景 (尤其是使用线程池) 下,由于 ThreadLocal.ThreadLocalMap 的底层数据结构导致 ThreadLocal 有内存泄漏的情况,应该尽可能在每次使用 ThreadLocal 后手动调用 remove(),以避免出现 ThreadLocal 经典的内存泄漏甚至是造成自身业务混乱的风险。 -**(三)可重入代码(Reentrant Code)** +### 3. 可重入代码(Reentrant Code) 这种代码也叫做纯代码(Pure Code),可以在代码执行的任何时刻中断它,转而去执行另外一段代码(包括递归调用它本身),而在控制权返回后,原来的程序不会出现任何错误。 diff --git a/notes/Socket.md b/notes/Socket.md index 482bafe6..7cb4fbf0 100644 --- a/notes/Socket.md +++ b/notes/Socket.md @@ -307,14 +307,14 @@ select 可移植性更好,几乎被所有主流平台所支持。 poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。 -需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。 - -需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。 - ### 3. epoll 应用场景 只需要运行在 Linux 平台上,并且有非常大量的描述符需要同时轮询,而且这些连接最好是长连接。 +需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。 + +需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。 + # 参考资料 - Stevens W R, Fenner B, Rudoff A M. UNIX network programming[M]. Addison-Wesley Professional, 2004. diff --git a/notes/设计模式.md b/notes/设计模式.md index 536072c2..d44d0e33 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -2952,7 +2952,7 @@ Java 利用缓存来加速大量小对象的访问时间。 - 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。 - 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。 - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 -- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 +- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

@@ -3004,6 +3004,7 @@ public class HighResolutionImage implements Image { ```java public class ImageProxy implements Image { + private HighResolutionImage highResolutionImage; public ImageProxy(HighResolutionImage highResolutionImage) { @@ -3027,6 +3028,7 @@ public class ImageProxy implements Image { ```java public class ImageViewer { + public static void main(String[] args) throws Exception { String image = "http://image.jpg"; URL url = new URL(image); From 5c5c056de67f7c7788b64c1b903c408f3a46d904 Mon Sep 17 00:00:00 2001 From: blueli <34030887+blueblueblueblueblueblue@users.noreply.github.com> Date: Mon, 10 Sep 2018 15:45:26 +0800 Subject: [PATCH 078/136] =?UTF-8?q?Update=20Java=20=E5=9F=BA=E7=A1=80.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 基础.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index d8f17cef..2cd0c825 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -196,9 +196,9 @@ String 不可变性天生具备线程安全,可以在多个线程中安全地 ## String Pool -字符串常量池(String Poll)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Poll 中。 +字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Pool 中。 -当一个字符串调用 intern() 方法时,如果 String Poll 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Poll 中字符串的引用;否则,就会在 String Poll 中添加一个新的字符串,并返回这个新字符串的引用。 +当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。 下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。 From e697abdc3d00a74e9b43ce1cb81cb9b4145202fb Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 10 Sep 2018 16:01:25 +0800 Subject: [PATCH 079/136] auto commit --- notes/Java 基础.md | 6 +-- notes/Java 容器.md | 6 +-- notes/Java 并发.md | 120 +++++++++------------------------------------ notes/设计模式.md | 4 +- 4 files changed, 31 insertions(+), 105 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index d8f17cef..b3aed5d6 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -196,9 +196,9 @@ String 不可变性天生具备线程安全,可以在多个线程中安全地 ## String Pool -字符串常量池(String Poll)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Poll 中。 +字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Poll 中。 -当一个字符串调用 intern() 方法时,如果 String Poll 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Poll 中字符串的引用;否则,就会在 String Poll 中添加一个新的字符串,并返回这个新字符串的引用。 +当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。 下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。 @@ -219,7 +219,7 @@ String s6 = "bbb"; System.out.println(s4 == s5); // true ``` -在 Java 7 之前,String Poll 被放在运行时常量池中,它属于永久代。而在 Java 7,String Poll 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 +在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 - [StackOverflow : What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning) - [深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index fd1ee97e..84189928 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -13,7 +13,7 @@ * [HashMap](#hashmap) * [ConcurrentHashMap](#concurrenthashmap) * [LinkedHashMap](#linkedhashmap) - * [WeekHashMap](#weekhashmap) + * [WeakHashMap](#weakhashmap) * [附录](#附录) * [参考资料](#参考资料) @@ -974,7 +974,7 @@ void afterNodeAccess(Node e) { // move node to last ### afterNodeInsertion() -在 put 等操作之后执行,当 removeEldestEntry() 方法返回 ture 时会移除最晚的节点,也就是链表首部节点 first。 +在 put 等操作之后执行,当 removeEldestEntry() 方法返回 true 时会移除最晚的节点,也就是链表首部节点 first。 evict 只有在构建 Map 的时候才为 false,在这里为 true。 @@ -1034,7 +1034,7 @@ public static void main(String[] args) { [3, 1, 4] ``` -## WeekHashMap +## WeakHashMap ### 存储结构 diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 03aaa9fd..add3982a 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -44,9 +44,10 @@ * [内存模型三大特性](#内存模型三大特性) * [先行发生原则](#先行发生原则) * [十一、线程安全](#十一线程安全) - * [线程安全定义](#线程安全定义) - * [线程安全分类](#线程安全分类) - * [线程安全的实现方法](#线程安全的实现方法) + * [不可变](#不可变) + * [互斥同步](#互斥同步) + * [非阻塞同步](#非阻塞同步) + * [无同步方案](#无同步方案) * [十二、锁优化](#十二锁优化) * [自旋锁](#自旋锁) * [锁消除](#锁消除) @@ -739,6 +740,7 @@ java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J. ```java public class CountdownLatchExample { + public static void main(String[] args) throws InterruptedException { final int totalThread = 10; CountDownLatch countDownLatch = new CountDownLatch(totalThread); @@ -787,6 +789,7 @@ public CyclicBarrier(int parties) { ```java public class CyclicBarrierExample { + public static void main(String[] args) { final int totalThread = 10; CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread); @@ -821,6 +824,7 @@ Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的 ```java public class SemaphoreExample { + public static void main(String[] args) { final int clientCount = 3; final int totalRequestCount = 10; @@ -865,6 +869,7 @@ FutureTask 可用于异步获取执行结果或取消执行任务的场景。当 ```java public class FutureTaskExample { + public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask = new FutureTask(new Callable() { @Override @@ -970,6 +975,7 @@ produce..produce..consume..consume..produce..consume..produce..consume..produce. ```java public class ForkJoinExample extends RecursiveTask { + private final int threshold = 5; private int first; private int last; @@ -1274,19 +1280,13 @@ Thread 对象的结束先行发生于 join() 方法返回。 # 十一、线程安全 -## 线程安全定义 +多个线程不管以何种方式访问某个类,并在在主调代码中不需要进行同步,都能表现正确的行为。 -一个类在可以被多个线程安全调用时就是线程安全的。 +线程安全有以下几种实现方式: -## 线程安全分类 +## 不可变 -线程安全不是一个非真即假的命题,可以将共享数据按照安全程度的强弱顺序分成以下五类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。 - -### 1. 不可变 - -不可变(Immutable)的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。只要一个不可变的对象被正确地构建出来,永远也不会看到它在多个线程之中处于不一致的状态。 - -多线程环境下,应当尽量使对象成为不可变,来满足线程安全。 +不可变(Immutable)的对象一定是线程安全的,不需要再采取任何的线程安全保障措施。只要一个不可变的对象被正确地构建出来,永远也不会看到它在多个线程之中处于不一致的状态。多线程环境下,应当尽量使对象成为不可变,来满足线程安全。 不可变的类型: @@ -1321,99 +1321,23 @@ public V put(K key, V value) { } ``` -### 2. 绝对线程安全 - -不管运行时环境如何,调用者都不需要任何额外的同步措施。 - -### 3. 相对线程安全 - -相对线程安全需要保证对这个对象单独的操作是线程安全的,在调用的时候不需要做额外的保障措施。但是对于一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段来保证调用的正确性。 - -在 Java 语言中,大部分的线程安全类都属于这种类型,例如 Vector、HashTable、Collections 的 synchronizedCollection() 方法包装的集合等。 - -对于下面的代码,如果删除元素的线程删除了 Vector 的一个元素,而获取元素的线程试图访问一个已经被删除的元素,那么就会抛出 ArrayIndexOutOfBoundsException。 - -```Java -public class VectorUnsafeExample { - private static Vector vector = new Vector<>(); - - public static void main(String[] args) { - while (true) { - for (int i = 0; i < 100; i++) { - vector.add(i); - } - ExecutorService executorService = Executors.newCachedThreadPool(); - executorService.execute(() -> { - for (int i = 0; i < vector.size(); i++) { - vector.remove(i); - } - }); - executorService.execute(() -> { - for (int i = 0; i < vector.size(); i++) { - vector.get(i); - } - }); - executorService.shutdown(); - } - } -} -``` - -```html -Exception in thread "Thread-159738" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 3 - at java.util.Vector.remove(Vector.java:831) - at VectorUnsafeExample.lambda$main$0(VectorUnsafeExample.java:14) - at VectorUnsafeExample$$Lambda$1/713338599.run(Unknown Source) - at java.lang.Thread.run(Thread.java:745) -``` - - -如果要保证上面的代码能正确执行下去,就需要对删除元素和获取元素的代码进行同步。 - -```java -executorService.execute(() -> { - synchronized (vector) { - for (int i = 0; i < vector.size(); i++) { - vector.remove(i); - } - } -}); -executorService.execute(() -> { - synchronized (vector) { - for (int i = 0; i < vector.size(); i++) { - vector.get(i); - } - } -}); -``` - -### 4. 线程兼容 - -线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全地使用,我们平常说一个类不是线程安全的,绝大多数时候指的是这一种情况。Java API 中大部分的类都是属于线程兼容的,如与前面的 Vector 和 HashTable 相对应的集合类 ArrayList 和 HashMap 等。 - -### 5. 线程对立 - -线程对立是指无论调用端是否采取了同步措施,都无法在多线程环境中并发使用的代码。由于 Java 语言天生就具备多线程特性,线程对立这种排斥多线程的代码是很少出现的,而且通常都是有害的,应当尽量避免。 - -## 线程安全的实现方法 - -### 1. 互斥同步 +## 互斥同步 synchronized 和 ReentrantLock。 -### 2. 非阻塞同步 +## 非阻塞同步 互斥同步最主要的问题就是线程阻塞和唤醒所带来的性能问题,因此这种同步也称为阻塞同步。 互斥同步属于一种悲观的并发策略,总是认为只要不去做正确的同步措施,那就肯定会出现问题。无论共享数据是否真的会出现竞争,它都要进行加锁(这里讨论的是概念模型,实际上虚拟机会优化掉很大一部分不必要的加锁)、用户态核心态转换、维护锁计数器和检查是否有被阻塞的线程需要唤醒等操作。 -**(一)CAS** +### 1. CAS 随着硬件指令集的发展,我们可以使用基于冲突检测的乐观并发策略:先进行操作,如果没有其它线程争用共享数据,那操作就成功了,否则采取补偿措施(不断地重试,直到成功为止)。这种乐观的并发策略的许多实现都不需要将线程阻塞,因此这种同步操作称为非阻塞同步。 乐观锁需要操作和冲突检测这两个步骤具备原子性,这里就不能再使用互斥同步来保证了,只能靠硬件来完成。硬件支持的原子性操作最典型的是:比较并交换(Compare-and-Swap,CAS)。CAS 指令需要有 3 个操作数,分别是内存地址 V、旧的预期值 A 和新值 B。当执行操作时,只有当 V 的值等于 A,才将 V 的值更新为 B。 -**(二)AtomicInteger** +### 2. AtomicInteger J.U.C 包里面的整数原子类 AtomicInteger 的方法调用了 Unsafe 类的 CAS 操作。 @@ -1450,17 +1374,17 @@ public final int getAndAddInt(Object var1, long var2, int var4) { } ``` -**(三)ABA** +### 3. ABA 如果一个变量初次读取的时候是 A 值,它的值被改成了 B,后来又被改回为 A,那 CAS 操作就会误认为它从来没有被改变过。 J.U.C 包提供了一个带有标记的原子引用类 AtomicStampedReference 来解决这个问题,它可以通过控制变量值的版本来保证 CAS 的正确性。大部分情况下 ABA 问题不会影响程序并发的正确性,如果需要解决 ABA 问题,改用传统的互斥同步可能会比原子类更高效。 -### 3. 无同步方案 +## 无同步方案 要保证线程安全,并不是一定就要进行同步。如果一个方法本来就不涉及共享数据,那它自然就无须任何同步措施去保证正确性。 -**(一)栈封闭** +### 1. 栈封闭 多个线程访问同一个方法的局部变量时,不会出现线程安全问题,因为局部变量存储在虚拟机栈中,属于线程私有的。 @@ -1491,7 +1415,7 @@ public static void main(String[] args) { 100 ``` -**(二)线程本地存储(Thread Local Storage)** +### 2. 线程本地存储(Thread Local Storage) 如果一段代码中所需要的数据必须与其他代码共享,那就看看这些共享数据的代码是否能保证在同一个线程中执行。如果能保证,我们就可以把共享数据的可见范围限制在同一个线程之内,这样,无须同步也能保证线程之间不出现数据争用的问题。 @@ -1597,7 +1521,7 @@ ThreadLocal 从理论上讲并不是用来解决多线程并发问题的,因 在一些场景 (尤其是使用线程池) 下,由于 ThreadLocal.ThreadLocalMap 的底层数据结构导致 ThreadLocal 有内存泄漏的情况,应该尽可能在每次使用 ThreadLocal 后手动调用 remove(),以避免出现 ThreadLocal 经典的内存泄漏甚至是造成自身业务混乱的风险。 -**(三)可重入代码(Reentrant Code)** +### 3. 可重入代码(Reentrant Code) 这种代码也叫做纯代码(Pure Code),可以在代码执行的任何时刻中断它,转而去执行另外一段代码(包括递归调用它本身),而在控制权返回后,原来的程序不会出现任何错误。 diff --git a/notes/设计模式.md b/notes/设计模式.md index 536072c2..d44d0e33 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -2952,7 +2952,7 @@ Java 利用缓存来加速大量小对象的访问时间。 - 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。 - 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。 - 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。 -- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。 +- 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

@@ -3004,6 +3004,7 @@ public class HighResolutionImage implements Image { ```java public class ImageProxy implements Image { + private HighResolutionImage highResolutionImage; public ImageProxy(HighResolutionImage highResolutionImage) { @@ -3027,6 +3028,7 @@ public class ImageProxy implements Image { ```java public class ImageViewer { + public static void main(String[] args) throws Exception { String image = "http://image.jpg"; URL url = new URL(image); From 07dff03dd49c3fb7d60ad9946bad0a878d67bc01 Mon Sep 17 00:00:00 2001 From: Yongtao Zhang Date: Tue, 11 Sep 2018 14:32:05 +0800 Subject: [PATCH 080/136] =?UTF-8?q?Update=20=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8E=9F=E7=90=86.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 高性能 MYSQL 在事务隔离级别中还有一个概念为加锁读。 --- notes/数据库系统原理.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index 1bcd2533..1ce774fa 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -294,12 +294,12 @@ SELECT ... FOR UPDATE; ---- -| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | -| :---: | :---: | :---:| :---: | -| 未提交读 | √ | √ | √ | -| 提交读 | × | √ | √ | -| 可重复读 | × | × | √ | -| 可串行化 | × | × | × | +| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | 加锁读 | +| :---: | :---: | :---:| :---: | :---: | +| 未提交读 | √ | √ | √ | × | +| 提交读 | × | √ | √ | × | +| 可重复读 | × | × | √ | × | +| 可串行化 | × | × | × | √ | # 五、多版本并发控制 From b88cef16b9032c0a8c98fa0cd01a55ac49307337 Mon Sep 17 00:00:00 2001 From: Yif_Corleone Date: Thu, 13 Sep 2018 18:08:37 +0800 Subject: [PATCH 081/136] =?UTF-8?q?Java=20=E5=9F=BA=E7=A1=80=20219?= =?UTF-8?q?=E8=A1=8C=E7=AC=94=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 应是 s5 == s6 --- notes/Java 基础.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 9da25851..22c94e60 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -216,7 +216,7 @@ System.out.println(s3 == s4); // true ```java String s5 = "bbb"; String s6 = "bbb"; -System.out.println(s4 == s5); // true +System.out.println(s5 == s6); // true ``` 在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 From d167aaf9961f7346afe850a49f903c6be819d658 Mon Sep 17 00:00:00 2001 From: Yif_Corleone Date: Thu, 13 Sep 2018 18:24:14 +0800 Subject: [PATCH 082/136] =?UTF-8?q?String=20poll=E7=AC=94=E8=AF=AF?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20227~272=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 基础.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 9da25851..8dcbff2a 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -226,9 +226,9 @@ System.out.println(s4 == s5); // true ## new String("abc") -使用这种方式一共会创建两个字符串对象(前提是 String Poll 中还没有 "abc" 字符串对象)。 +使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 "abc" 字符串对象)。 -- "abc" 属于字符串字面量,因此编译时期会在 String Poll 中创建一个字符串对象,指向这个 "abc" 字符串字面量; +- "abc" 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 "abc" 字符串字面量; - 而使用 new 的方式会在堆中创建一个字符串对象。 创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。 @@ -267,7 +267,7 @@ Constant pool: // ... ``` -在 Constant Poll 中,#19 存储这字符串字面量 "abc",#3 是 String Poll 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Poll 中的字符串对象作为 String 构造函数的参数。 +在 Constant Pool 中,#19 存储这字符串字面量 "abc",#3 是 String Pool 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 构造函数的参数。 以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。 From b751fc80239a6ef8991c2c8019937bee2a87883b Mon Sep 17 00:00:00 2001 From: Yif_Corleone Date: Fri, 14 Sep 2018 11:32:07 +0800 Subject: [PATCH 083/136] =?UTF-8?q?Java=20=E5=9F=BA=E7=A1=80=EF=BC=8C?= =?UTF-8?q?=E5=AF=B9final=E5=85=B3=E9=94=AE=E5=AD=97=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E5=99=A8=E7=9B=B8=E5=85=B3=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 基础.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index bc856d4d..c5aac14e 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -1042,6 +1042,10 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 声明类不允许被继承。 +**4. 构造器** + +声明类不允许被`new`实例化,多用于`Singleton`模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 + ## static **1. 静态变量** From f2e8961f3706020cd17dd4e758851c7c9f4a312e Mon Sep 17 00:00:00 2001 From: Yif_Corleone Date: Fri, 14 Sep 2018 14:13:33 +0800 Subject: [PATCH 084/136] =?UTF-8?q?Java=20=E5=9F=BA=E7=A1=80=20=E2=80=9C?= =?UTF-8?q?=E9=9A=90=E5=BC=8F=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2=E2=80=9D?= =?UTF-8?q?=E4=B8=AD++=E5=92=8C+=3D=E6=95=88=E6=9E=9C=E4=B8=80=E6=A0=B7?= =?UTF-8?q?=EF=BC=8C=E4=B9=9F=E4=BC=9A=E6=89=A7=E8=A1=8C=E9=9A=90=E5=BC=8F?= =?UTF-8?q?=E7=9A=84=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/Java 基础.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index c5aac14e..9992d1ec 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -368,10 +368,11 @@ short s1 = 1; // s1 = s1 + 1; ``` -但是使用 += 运算符可以执行隐式类型转换。 +但是使用 += 或 ++ 运算符可以执行隐式类型转换。 ```java s1 += 1; +// s1++; ``` 上面的语句相当于将 s1 + 1 的计算结果进行了向下转型: From 60ed4f498ca07d3ef6058dd5f783c8156ab97413 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 14 Sep 2018 21:35:10 +0800 Subject: [PATCH 085/136] auto commit --- notes/Java IO.md | 7 ++++--- notes/Java 基础.md | 21 +++++++++++++-------- notes/Java 并发.md | 5 +++++ notes/剑指 offer 题解.md | 2 +- notes/数据库系统原理.md | 12 ++++++------ notes/缓存.md | 4 +++- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index acb95b36..a2dd668b 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -69,16 +69,17 @@ public static void listAllFiles(File dir) { ```java public static void copyFile(String src, String dist) throws IOException { - FileInputStream in = new FileInputStream(src); FileOutputStream out = new FileOutputStream(dist); + byte[] buffer = new byte[20 * 1024]; + int cnt; // read() 最多读取 buffer.length 个字节 // 返回的是实际读取的个数 // 返回 -1 的时候表示读到 eof,即文件尾 - while (in.read(buffer, 0, buffer.length) != -1) { - out.write(buffer); + while ((cnt = in.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, cnt); } in.close(); diff --git a/notes/Java 基础.md b/notes/Java 基础.md index d8f17cef..0087fde7 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -196,9 +196,9 @@ String 不可变性天生具备线程安全,可以在多个线程中安全地 ## String Pool -字符串常量池(String Poll)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Poll 中。 +字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Pool 中。 -当一个字符串调用 intern() 方法时,如果 String Poll 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Poll 中字符串的引用;否则,就会在 String Poll 中添加一个新的字符串,并返回这个新字符串的引用。 +当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个新字符串的引用。 下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。 @@ -216,19 +216,19 @@ System.out.println(s3 == s4); // true ```java String s5 = "bbb"; String s6 = "bbb"; -System.out.println(s4 == s5); // true +System.out.println(s5 == s6); // true ``` -在 Java 7 之前,String Poll 被放在运行时常量池中,它属于永久代。而在 Java 7,String Poll 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 +在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 - [StackOverflow : What is String interning?](https://stackoverflow.com/questions/10578984/what-is-string-interning) - [深入解析 String#intern](https://tech.meituan.com/in_depth_understanding_string_intern.html) ## new String("abc") -使用这种方式一共会创建两个字符串对象(前提是 String Poll 中还没有 "abc" 字符串对象)。 +使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 "abc" 字符串对象)。 -- "abc" 属于字符串字面量,因此编译时期会在 String Poll 中创建一个字符串对象,指向这个 "abc" 字符串字面量; +- "abc" 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 "abc" 字符串字面量; - 而使用 new 的方式会在堆中创建一个字符串对象。 创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。 @@ -267,7 +267,7 @@ Constant pool: // ... ``` -在 Constant Poll 中,#19 存储这字符串字面量 "abc",#3 是 String Poll 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Poll 中的字符串对象作为 String 构造函数的参数。 +在 Constant Pool 中,#19 存储这字符串字面量 "abc",#3 是 String Pool 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 构造函数的参数。 以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。 @@ -368,10 +368,11 @@ short s1 = 1; // s1 = s1 + 1; ``` -但是使用 += 运算符可以执行隐式类型转换。 +但是使用 += 或者 ++ 运算符可以执行隐式类型转换。 ```java s1 += 1; +// s1++; ``` 上面的语句相当于将 s1 + 1 的计算结果进行了向下转型: @@ -1042,6 +1043,10 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 声明类不允许被继承。 +**4. 构造器** + +声明类不允许被 `new` 实例化,多用于 `Singleton` 模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 + ## static **1. 静态变量** diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 977d85f2..add3982a 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -740,6 +740,7 @@ java.util.concurrent(J.U.C)大大提高了并发性能,AQS 被认为是 J. ```java public class CountdownLatchExample { + public static void main(String[] args) throws InterruptedException { final int totalThread = 10; CountDownLatch countDownLatch = new CountDownLatch(totalThread); @@ -788,6 +789,7 @@ public CyclicBarrier(int parties) { ```java public class CyclicBarrierExample { + public static void main(String[] args) { final int totalThread = 10; CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread); @@ -822,6 +824,7 @@ Semaphore 类似于操作系统中的信号量,可以控制对互斥资源的 ```java public class SemaphoreExample { + public static void main(String[] args) { final int clientCount = 3; final int totalRequestCount = 10; @@ -866,6 +869,7 @@ FutureTask 可用于异步获取执行结果或取消执行任务的场景。当 ```java public class FutureTaskExample { + public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask = new FutureTask(new Callable() { @Override @@ -971,6 +975,7 @@ produce..produce..consume..consume..produce..consume..produce..consume..produce. ```java public class ForkJoinExample extends RecursiveTask { + private final int threshold = 5; private int first; private int last; diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 2c8f2822..2c2be5b2 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1154,7 +1154,7 @@ public ListNode FindKthToTail(ListNode head, int k) { ## 解题思路 -使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 z1 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 +使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y4 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。 diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index 1bcd2533..1ce774fa 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -294,12 +294,12 @@ SELECT ... FOR UPDATE; ---- -| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | -| :---: | :---: | :---:| :---: | -| 未提交读 | √ | √ | √ | -| 提交读 | × | √ | √ | -| 可重复读 | × | × | √ | -| 可串行化 | × | × | × | +| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | 加锁读 | +| :---: | :---: | :---:| :---: | :---: | +| 未提交读 | √ | √ | √ | × | +| 提交读 | × | √ | √ | × | +| 可重复读 | × | × | √ | × | +| 可串行化 | × | × | × | √ | # 五、多版本并发控制 diff --git a/notes/缓存.md b/notes/缓存.md index 8f7449bf..07a9e866 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -99,7 +99,7 @@ public class LRU implements Iterable { if (map.size() > maxSize) { Node toRemove = removeTail(); - map.remove(toRemove); + map.remove(toRemove.k); } } @@ -114,6 +114,7 @@ public class LRU implements Iterable { private void appendHead(Node node) { node.next = head.next; + node.next.pre = node; node.pre = head; head.next = node; } @@ -122,6 +123,7 @@ public class LRU implements Iterable { private Node removeTail() { Node node = tail.pre; tail.pre = node.pre; + node.pre.next = tail; return node; } From 325595d41bd597a57a102b75150e939aafa7e42f Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 14 Sep 2018 22:13:46 +0800 Subject: [PATCH 086/136] auto commit --- notes/Java 基础.md | 2 +- notes/剑指 offer 题解.md | 2 +- pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png | Bin 0 -> 17408 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 5bb41ea6..0087fde7 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -1045,7 +1045,7 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 **4. 构造器** -声明类不允许被`new`实例化,多用于`Singleton`模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 +声明类不允许被 `new` 实例化,多用于 `Singleton` 模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 ## static diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 2c2be5b2..a797eaa1 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1158,7 +1158,7 @@ public ListNode FindKthToTail(ListNode head, int k) { 在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。 -

+

```java public ListNode EntryNodeOfLoop(ListNode pHead) { diff --git a/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png b/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png new file mode 100644 index 0000000000000000000000000000000000000000..0d28e99622f41e6d1d67f1d1d4f94cef7505530b GIT binary patch literal 17408 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 literal 0 HcmV?d00001 From 170f0fc3eb056c5b8ad4f16f5bac5396bcad250e Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 14 Sep 2018 22:14:52 +0800 Subject: [PATCH 087/136] auto commit --- notes/剑指 offer 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index a797eaa1..4af993dd 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1154,7 +1154,7 @@ public ListNode FindKthToTail(ListNode head, int k) { ## 解题思路 -使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y4 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 +使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y6 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。 From b802b8add8fa367d09494c37fe20c13e123b14a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=81=AA=E5=A8=81?= Date: Sun, 16 Sep 2018 14:17:21 +0800 Subject: [PATCH 088/136] =?UTF-8?q?Update=20=E5=89=91=E6=8C=87=20offer=20?= =?UTF-8?q?=E9=A2=98=E8=A7=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/剑指 offer 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 4af993dd..e1a87b5b 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1559,7 +1559,7 @@ public ArrayList> Print(TreeNode pRoot) { 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。 -例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。 +例如,下图是后序遍历序列 1,3,2 所对应的二叉搜索树。

From 55f1d4e2f53effb4e75e349ccf9b278060bf62f3 Mon Sep 17 00:00:00 2001 From: 0xl2oot <0xl2oot@gmail.com> Date: Mon, 17 Sep 2018 21:42:01 +0800 Subject: [PATCH 089/136] Update SUMMARY.md --- SUMMARY.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index 69b6103c..a864c37f 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -27,10 +27,23 @@ This file used to generate gitbook catalogue. * [Java 虚拟机](/notes/Java 虚拟机.md) * [Java 并发](/notes/Java 并发.md) * [Java 容器](/notes/Java 容器.md) - * [Java I/O](/notes/Java I/O.md) -* 分布式 - * [一致性](/notes/一致性.md) - * [分布式问题分析](/notes/分布式问题分析.md) - - + * [Java I/O](/notes/Java IO.md) +* 系统设计 + * [系统设计基础](/notes/系统设计基础.md) + * [分布式](/notes/分布式.md) + * [集群](/notes/集群.md) + * [攻击技术](/notes/攻击技术.md) + * [缓存](/notes/缓存.md) + * [消息队列](/notes/消息队列.md) +* 工具 + * [Git](/notes/Git.md) + * [Docker](/notes/Docker.md) + * [正则表达式](/notes/正则表达式.md) + * [构建工具](/notes/构建工具.md) +* 编码实践 + * [重构](/notes/重构.md) + * [代码可读性](/notes/代码可读性.md) + * [代码风格规范](/notes/代码风格规范.md) +* 参考书目 + * [BOOKLIST](/BOOKLIST.md) From e56a80629286fad24633654a1b27494081952b53 Mon Sep 17 00:00:00 2001 From: Yif_Corleone Date: Tue, 18 Sep 2018 00:44:56 +0800 Subject: [PATCH 090/136] Java --- notes/Java 基础.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 0087fde7..eb3572cd 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -1043,10 +1043,6 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 声明类不允许被继承。 -**4. 构造器** - -声明类不允许被 `new` 实例化,多用于 `Singleton` 模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 - ## static **1. 静态变量** From 338d0bff7fab7d27537b91b1c48a1d035991e527 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 18 Sep 2018 09:31:50 +0800 Subject: [PATCH 091/136] auto commit --- notes/Java 基础.md | 4 ---- notes/剑指 offer 题解.md | 2 +- notes/计算机操作系统.md | 2 +- notes/设计模式.md | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 0087fde7..eb3572cd 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -1043,10 +1043,6 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 声明类不允许被继承。 -**4. 构造器** - -声明类不允许被 `new` 实例化,多用于 `Singleton` 模式中。如果该类有子类需要继承,若该类无其他构造器,则不允许被继承。 - ## static **1. 静态变量** diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 4af993dd..e1a87b5b 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1559,7 +1559,7 @@ public ArrayList> Print(TreeNode pRoot) { 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。 -例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。 +例如,下图是后序遍历序列 1,3,2 所对应的二叉搜索树。

diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index e6c462a6..c0c4364e 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -1038,7 +1038,7 @@ gcc -o hello hello.c ## 静态链接 -静态连接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务: +静态链接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务: - 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。 - 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。 diff --git a/notes/设计模式.md b/notes/设计模式.md index d44d0e33..3b53a66a 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -177,7 +177,7 @@ public class Singleton { #### Ⅵ 枚举实现 - ```java +```java public enum Singleton { INSTANCE; From 57a741092b3d04dcb7f4019e1fa7cbcd47a6db17 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 18 Sep 2018 09:33:33 +0800 Subject: [PATCH 092/136] auto commit --- notes/设计模式.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index 3b53a66a..8c9f0b22 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -217,7 +217,7 @@ public enum Singleton { } } } - ``` +``` 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 From f89ef4cf591d2ef04f89e3428fc2af34be56617d Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 18 Sep 2018 09:42:24 +0800 Subject: [PATCH 093/136] auto commit --- notes/设计模式.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/notes/设计模式.md b/notes/设计模式.md index 8c9f0b22..c177ff92 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -276,6 +276,7 @@ public class ConcreteProduct2 implements Product { ```java public class Client { + public static void main(String[] args) { int type = 1; Product product; @@ -295,6 +296,7 @@ public class Client { ```java public class SimpleFactory { + public Product createProduct(int type) { if (type == 1) { return new ConcreteProduct1(); @@ -308,6 +310,7 @@ public class SimpleFactory { ```java public class Client { + public static void main(String[] args) { SimpleFactory simpleFactory = new SimpleFactory(); Product product = simpleFactory.createProduct(1); From e3c63b6637f4a95981c4a6b54286667daab01c06 Mon Sep 17 00:00:00 2001 From: Yutong Wang Date: Mon, 17 Sep 2018 21:50:19 -0700 Subject: [PATCH 094/136] Simplify House Robber solution --- notes/Leetcode 题解.md | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 04a751c7..2d6b2d5f 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2415,27 +2415,19 @@ public int climbStairs(int n) { 定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。 由于不能抢劫邻近住户,因此如果抢劫了第 i 个住户那么只能抢劫 i - 2 或者 i - 3 的住户,所以 - -

+dp[i] = max(dp[i-1], dp[i-2] + nums[i])
```java public int rob(int[] nums) { - int n = nums.length; - if (n == 0) { - return 0; - } - if (n == 1) { - return nums[0]; - } - int pre3 = 0, pre2 = 0, pre1 = 0; - for (int i = 0; i < n; i++) { - int cur = Math.max(pre2, pre3) + nums[i]; - pre3 = pre2; + int pre2 = 0, pre1 = 0; + for (int i = 0; i < nums.length; i++) { + int cur = Math.max(pre2 + nums[i], pre1); pre2 = pre1; pre1 = cur; } - return Math.max(pre1, pre2); + return pre1; } + ``` **强盗在环形街区抢劫** @@ -2443,7 +2435,7 @@ public int rob(int[] nums) { [213. House Robber II (Medium)](https://leetcode.com/problems/house-robber-ii/description/) ```java -public int rob(int[] nums) { +public int rob(int[] nums) { if (nums == null || nums.length == 0) { return 0; } @@ -2454,15 +2446,14 @@ public int rob(int[] nums) { return Math.max(rob(nums, 0, n - 2), rob(nums, 1, n - 1)); } -private int rob(int[] nums, int first, int last) { - int pre3 = 0, pre2 = 0, pre1 = 0; +private int rob(int[] nums, int first, int last) { + int pre2 = 0, pre1 = 0; for (int i = first; i <= last; i++) { - int cur = Math.max(pre3, pre2) + nums[i]; - pre3 = pre2; + int cur = Math.max(pre1, pre2 + nums[i]); pre2 = pre1; pre1 = cur; } - return Math.max(pre2, pre1); + return pre1; } ``` From 497812bd4232da65e88b9e7628a0e7de5abb3030 Mon Sep 17 00:00:00 2001 From: Yutong Wang Date: Mon, 17 Sep 2018 23:40:06 -0700 Subject: [PATCH 095/136] Fix a bug in the Minimum Path Sum solution Check boundary --- notes/Leetcode 题解.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 2d6b2d5f..d09ff18d 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2505,9 +2505,9 @@ public int minPathSum(int[][] grid) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0) { - dp[j] = dp[j - 1]; + if (j>0) dp[j] = dp[j - 1]; } else { - dp[j] = Math.min(dp[j - 1], dp[j]); + if (j>0) dp[j] = Math.min(dp[j - 1], dp[j]); } dp[j] += grid[i][j]; } From 177a4325950ebebbfcc69c9c9a41d31ddba091d3 Mon Sep 17 00:00:00 2001 From: Jingui Ren <1198980993@qq.com> Date: Tue, 18 Sep 2018 10:31:09 +0000 Subject: [PATCH 096/136] =?UTF-8?q?mask=E8=AE=A1=E7=AE=97=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当mask = 11011000的时候,mask |= mask >> 2这个时候的值应该为11111110 --- notes/Java 容器.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 84189928..e42a42f0 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -738,7 +738,7 @@ HashMap 构造函数允许用户传入的容量不是 2 的 n 次方,因为它 ``` mask |= mask >> 1 11011000 -mask |= mask >> 2 11111100 +mask |= mask >> 2 11111110 mask |= mask >> 4 11111111 ``` From 642411cdc62dde62b7e9bfbc583a3cd3624e9633 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 19 Sep 2018 12:56:03 +0800 Subject: [PATCH 097/136] auto commit --- notes/Java 基础.md | 11 +++---- notes/Java 容器.md | 2 +- notes/Leetcode 题解.md | 28 ++++++------------ notes/MySQL.md | 2 +- notes/剑指 offer 题解.md | 6 ++-- notes/数据库系统原理.md | 12 ++++---- notes/算法.md | 6 ++-- notes/系统设计基础.md | 5 ++++ notes/缓存.md | 4 ++- notes/计算机操作系统.md | 2 +- notes/设计模式.md | 7 +++-- pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png | Bin 0 -> 17408 bytes 12 files changed, 43 insertions(+), 42 deletions(-) create mode 100644 pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png diff --git a/notes/Java 基础.md b/notes/Java 基础.md index 9da25851..eb3572cd 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -216,7 +216,7 @@ System.out.println(s3 == s4); // true ```java String s5 = "bbb"; String s6 = "bbb"; -System.out.println(s4 == s5); // true +System.out.println(s5 == s6); // true ``` 在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。 @@ -226,9 +226,9 @@ System.out.println(s4 == s5); // true ## new String("abc") -使用这种方式一共会创建两个字符串对象(前提是 String Poll 中还没有 "abc" 字符串对象)。 +使用这种方式一共会创建两个字符串对象(前提是 String Pool 中还没有 "abc" 字符串对象)。 -- "abc" 属于字符串字面量,因此编译时期会在 String Poll 中创建一个字符串对象,指向这个 "abc" 字符串字面量; +- "abc" 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 "abc" 字符串字面量; - 而使用 new 的方式会在堆中创建一个字符串对象。 创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。 @@ -267,7 +267,7 @@ Constant pool: // ... ``` -在 Constant Poll 中,#19 存储这字符串字面量 "abc",#3 是 String Poll 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Poll 中的字符串对象作为 String 构造函数的参数。 +在 Constant Pool 中,#19 存储这字符串字面量 "abc",#3 是 String Pool 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0: 行使用 new #2 在堆中创建一个字符串对象,并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 构造函数的参数。 以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。 @@ -368,10 +368,11 @@ short s1 = 1; // s1 = s1 + 1; ``` -但是使用 += 运算符可以执行隐式类型转换。 +但是使用 += 或者 ++ 运算符可以执行隐式类型转换。 ```java s1 += 1; +// s1++; ``` 上面的语句相当于将 s1 + 1 的计算结果进行了向下转型: diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 84189928..e42a42f0 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -738,7 +738,7 @@ HashMap 构造函数允许用户传入的容量不是 2 的 n 次方,因为它 ``` mask |= mask >> 1 11011000 -mask |= mask >> 2 11111100 +mask |= mask >> 2 11111110 mask |= mask >> 4 11111111 ``` diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 04a751c7..def70c60 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2420,21 +2420,13 @@ public int climbStairs(int n) { ```java public int rob(int[] nums) { - int n = nums.length; - if (n == 0) { - return 0; - } - if (n == 1) { - return nums[0]; - } - int pre3 = 0, pre2 = 0, pre1 = 0; - for (int i = 0; i < n; i++) { - int cur = Math.max(pre2, pre3) + nums[i]; - pre3 = pre2; + int pre2 = 0, pre1 = 0; + for (int i = 0; i < nums.length; i++) { + int cur = Math.max(pre2 + nums[i], pre1); pre2 = pre1; pre1 = cur; } - return Math.max(pre1, pre2); + return pre1; } ``` @@ -2443,7 +2435,7 @@ public int rob(int[] nums) { [213. House Robber II (Medium)](https://leetcode.com/problems/house-robber-ii/description/) ```java -public int rob(int[] nums) { +public int rob(int[] nums) { if (nums == null || nums.length == 0) { return 0; } @@ -2454,15 +2446,14 @@ public int rob(int[] nums) { return Math.max(rob(nums, 0, n - 2), rob(nums, 1, n - 1)); } -private int rob(int[] nums, int first, int last) { - int pre3 = 0, pre2 = 0, pre1 = 0; +private int rob(int[] nums, int first, int last) { + int pre2 = 0, pre1 = 0; for (int i = first; i <= last; i++) { - int cur = Math.max(pre3, pre2) + nums[i]; - pre3 = pre2; + int cur = Math.max(pre1, pre2 + nums[i]); pre2 = pre1; pre1 = cur; } - return Math.max(pre2, pre1); + return pre1; } ``` @@ -7063,4 +7054,3 @@ public int[] countBits(int num) { - 何海涛, 软件工程师. 剑指 Offer: 名企面试官精讲典型编程题[M]. 电子工业出版社, 2014. - 《编程之美》小组. 编程之美[M]. 电子工业出版社, 2008. - 左程云. 程序员代码面试指南[M]. 电子工业出版社, 2015. - diff --git a/notes/MySQL.md b/notes/MySQL.md index 2c5d8935..f5479685 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -374,7 +374,7 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提 ### 2. 连接 -可以将原来的连接分解成多个单表连接查询,然后在用户程序中进行连接。 +可以将原来的连接分解成多个单表查询,然后在用户程序中进行连接。 ### 3. ID 唯一性 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 2c8f2822..e1a87b5b 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -1154,11 +1154,11 @@ public ListNode FindKthToTail(ListNode head, int k) { ## 解题思路 -使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 z1 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 +使用双指针,一个指针 fast 每次移动两个节点,一个指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。假设相遇点在下图的 y6 位置,此时 fast 移动的节点数为 x+2y+z,slow 为 x+y,由于 fast 速度比 slow 快一倍,因此 x+2y+z=2(x+y),得到 x=z。 在相遇点,slow 要到环的入口点还需要移动 z 个节点,如果让 fast 重新从头开始移动,并且速度变为每次移动一个节点,那么它到环入口点还需要移动 x 个节点。在上面已经推导出 x=z,因此 fast 和 slow 将在环入口点相遇。 -

+

```java public ListNode EntryNodeOfLoop(ListNode pHead) { @@ -1559,7 +1559,7 @@ public ArrayList> Print(TreeNode pRoot) { 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。假设输入的数组的任意两个数字都互不相同。 -例如,下图是后序遍历序列 3,1,2 所对应的二叉搜索树。 +例如,下图是后序遍历序列 1,3,2 所对应的二叉搜索树。

diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index 1bcd2533..1ce774fa 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -294,12 +294,12 @@ SELECT ... FOR UPDATE; ---- -| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | -| :---: | :---: | :---:| :---: | -| 未提交读 | √ | √ | √ | -| 提交读 | × | √ | √ | -| 可重复读 | × | × | √ | -| 可串行化 | × | × | × | +| 隔离级别 | 脏读 | 不可重复读 | 幻影读 | 加锁读 | +| :---: | :---: | :---:| :---: | :---: | +| 未提交读 | √ | √ | √ | × | +| 提交读 | × | √ | √ | × | +| 可重复读 | × | × | √ | × | +| 可串行化 | × | × | × | √ | # 五、多版本并发控制 diff --git a/notes/算法.md b/notes/算法.md index cb83830b..1bc0690a 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -459,7 +459,7 @@ public abstract class MergeSort> extends Sort { 将一个大数组分成两个小数组去求解。 -因为每次都将问题对半分成两个子问题,而这种对半分的算法复杂度一般为 O(NlogN),因此该归并排序方法的时间复杂度也为 O(NlogN)。 +因为每次都将问题对半分成两个子问题,这种对半分的算法复杂度一般为 O(NlogN)。 ```java public class Up2DownMergeSort> extends MergeSort { @@ -617,7 +617,7 @@ public class ThreeWayQuickSort> extends QuickSort { 可以利用这个特性找出数组的第 k 个元素。 -该算法是线性级别的,因为每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。 +该算法是线性级别的,假设每次能将数组二分,那么比较的总次数为 (N+N/2+N/4+..),直到找到第 k 个元素,这个和显然小于 2N。 ```java public T select(T[] nums, int k) { @@ -2292,7 +2292,7 @@ from H1 to H3 可以将每种字符转换成二进制编码,例如将 a 转换为 00,b 转换为 01,c 转换为 10,d 转换为 11。这是最简单的一种编码方式,没有考虑各个字符的权值(出现频率)。而哈夫曼编码采用了贪心策略,使出现频率最高的字符的编码最短,从而保证整体的编码长度最短。 -首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点在树的最底层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 +首先生成一颗哈夫曼树,每次生成过程中选取频率最少的两个节点,生成一个新节点作为它们的父节点,并且新节点的频率为两个节点的和。选取频率最少的原因是,生成过程使得先选取的节点位于树的更低层,那么需要的编码长度更长,频率更少可以使得总编码长度更少。 生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。 diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index 4a961140..ffa5de70 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -4,6 +4,7 @@ * [三、扩展性](#三扩展性) * [四、可用性](#四可用性) * [五、安全性](#五安全性) +* [参考资料](#参考资料) @@ -102,3 +103,7 @@ # 五、安全性 要求系统的应对各种攻击手段时能够有可靠的应对措施。 + +# 参考资料 + +- 大型网站技术架构:核心原理与案例分析 diff --git a/notes/缓存.md b/notes/缓存.md index 8f7449bf..07a9e866 100644 --- a/notes/缓存.md +++ b/notes/缓存.md @@ -99,7 +99,7 @@ public class LRU implements Iterable { if (map.size() > maxSize) { Node toRemove = removeTail(); - map.remove(toRemove); + map.remove(toRemove.k); } } @@ -114,6 +114,7 @@ public class LRU implements Iterable { private void appendHead(Node node) { node.next = head.next; + node.next.pre = node; node.pre = head; head.next = node; } @@ -122,6 +123,7 @@ public class LRU implements Iterable { private Node removeTail() { Node node = tail.pre; tail.pre = node.pre; + node.pre.next = tail; return node; } diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index e6c462a6..c0c4364e 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -1038,7 +1038,7 @@ gcc -o hello hello.c ## 静态链接 -静态连接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务: +静态链接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务: - 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。 - 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。 diff --git a/notes/设计模式.md b/notes/设计模式.md index d44d0e33..c177ff92 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -177,7 +177,7 @@ public class Singleton { #### Ⅵ 枚举实现 - ```java +```java public enum Singleton { INSTANCE; @@ -217,7 +217,7 @@ public enum Singleton { } } } - ``` +``` 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 @@ -276,6 +276,7 @@ public class ConcreteProduct2 implements Product { ```java public class Client { + public static void main(String[] args) { int type = 1; Product product; @@ -295,6 +296,7 @@ public class Client { ```java public class SimpleFactory { + public Product createProduct(int type) { if (type == 1) { return new ConcreteProduct1(); @@ -308,6 +310,7 @@ public class SimpleFactory { ```java public class Client { + public static void main(String[] args) { SimpleFactory simpleFactory = new SimpleFactory(); Product product = simpleFactory.createProduct(1); diff --git a/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png b/pics/70fa1f83-dae7-456d-b94b-ce28963b2ba1.png new file mode 100644 index 0000000000000000000000000000000000000000..0d28e99622f41e6d1d67f1d1d4f94cef7505530b GIT binary patch literal 17408 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 literal 0 HcmV?d00001 From c7ce8a05a515d203582e5313b95509685c68492c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=99=BA=E6=85=A7?= Date: Wed, 19 Sep 2018 15:54:20 +0800 Subject: [PATCH 098/136] =?UTF-8?q?[BUG=5FFIX]=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E9=94=99=E8=AF=AF=EF=BC=8C=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=E7=89=B9=E6=80=A7=E4=B8=BA=20ACID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes/分布式.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notes/分布式.md b/notes/分布式.md index a39ae35e..d2b2f974 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -99,7 +99,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 # 二、分布式事务 -指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。 +指事务的操作位于不同的节点上,需要保证事务的 ACID 特性。 例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。 @@ -335,4 +335,5 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。 - [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) - [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) - [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) +- [ACID](https://en.wikipedia.org/wiki/ACID_(computer_science)) From 9aa420219f83fb941cb91c8304dcb4a5ba0aa331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= Date: Thu, 20 Sep 2018 00:12:26 +0800 Subject: [PATCH 099/136] Update README.md --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ded19a67..116e2a4b 100644 --- a/README.md +++ b/README.md @@ -208,25 +208,28 @@ Power by [logomakr](https://logomakr.com/). 感谢以下人员对本仓库做出的贡献,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与笔者联系。 - + - + - + - + - + - + - + + + + #### License From 6a24574d06decb0491a8d7a76b0649c6cdea2619 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 20 Sep 2018 00:18:03 +0800 Subject: [PATCH 100/136] auto commit --- other/10072416.jpg | Bin 25142 -> 0 bytes other/15684156.jpg | Bin 19687 -> 0 bytes other/18458140.jpg | Bin 18490 -> 0 bytes other/21679154.png | Bin 35639 -> 0 bytes other/22954582.jpg | Bin 27133 -> 0 bytes other/7719370.png | Bin 158793 -> 0 bytes other/8018776.jpg | Bin 9600 -> 0 bytes 7 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 other/10072416.jpg delete mode 100644 other/15684156.jpg delete mode 100644 other/18458140.jpg delete mode 100644 other/21679154.png delete mode 100644 other/22954582.jpg delete mode 100644 other/7719370.png delete mode 100644 other/8018776.jpg diff --git a/other/10072416.jpg b/other/10072416.jpg deleted file mode 100644 index 746fe860ec00eae7fa28a8d84aef6a992294fee4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25142 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 t5+yeszBP9k_CKCvYmbwT-KryN9Qjw@>JY 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 diff --git a/other/18458140.jpg b/other/18458140.jpg deleted file mode 100644 index 4ce2000172d25e6f41cd48d5ea81fe67e73a880a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18490 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 diff --git a/other/21679154.png b/other/21679154.png deleted file mode 100644 index bfc24d5690bda13c82e2be39c47f80e6d88c6194..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35639 zcmX7wWmp_dvxbobCuo2rxVtPG+})kvuEE{i-CY9&cZcBa?(V_e$(i?jT(B3rKW2KW ztE;Q-dV0eZ`M3f*PAWi@KgM$J-nGq=wgn;makQ5PAamzY;hj-Ju z?>ven#HSY@i?^n4A|G=>ACk(#;a-jlBA25=rJzuTyF>qR+(2#@x~ZE1&i0kgghH89 z`f>b|68UGz+ZebgZZilGewt1gE|sh}?vtV6(#jcCIEH2&=}08I)%|7dA3?>K$wyBY zNx3_Ziv#;#g@wvmN0n0_ig#S6wdmwhN&2w5$B0yl1^rG1WFX-Ewtys9N<07U-q}5$ z(cp(tLKM0>NuO|CboCC3k94i4`U%#y*vX^nu9UGk9CUB(2gglKkV%`6#c>@DM4ZWxxe) zxGUA~o}de+<7$HUx1XAi7Z7=Q(DuSxCdCO^P&IdE`aCLR6SXs1x@WHgwM1@GmQ=tq z_~0u>OeHB6j*b^bQIkEi7r3X);obe(eh{=Z`w#R{y*8!o zD*U(Yl(M>=Z;Ma*zxfXD22*$x=r82%XjpdVPL~-wQ+UWz22T7&2(H;^zuIVL%9hJ9 zJO6(R1cXuKm1;gXJ&3at;Gql^+q{aETb`#z{a6@Smvtf${C%=Ts>OYwo&2)8lqkd) z9Ig~A8IB%s6&&o-=@~eJ&5!%p!{1<;S>AfD=lTqK*WQ#EF1SXXZ!$Do<^R2ncjL}A zRa484dw06~(?PsZjyRk&~hqxMVL! z(X1*T7>NA;3{f%h;9;a0`#}aLD3y&-DN2Nd8Vd_+$Un~W-p1xcZp9H5&a6AsuGanW zQ7Z4t&{E=Z_-jUN%SDfuSWpBkpBq{E=8BSU|HNaFQclMC5^iqw^t!Hs*Vn=Bs<+0D z(llCX8t4eKUDbj*Oe51}S28*<+sg_SGg7uvm?^--4a4T6K8$Q#%k!mp-_&ycvHRg_ z?CXucR3saFT9w;z5t1ZFIog^pf}xb%I{7Pa-Vl=>@DE~o-i^AA%e~w;d=$w!&-5yf ze*R~ixlW?4i;#Kza-}F6=_c5uXw5Nwlc(N!7R0FV+>%0F&Bti zM;yDV82-ROFkt*cr1zLsfOAJ8EZ=uF%n*>Pke-@k}!S(PtX*2}*CoA;$2y1T#s93a>{w0GTt;_RG#e2NG| ze4mNBxf$X6R*UpR%_LfX{6vNS8oqB{te7bYxDedI0QSDE?ZHF1-s3E2}Dj z{argwFhBoO_q^{0!Bl=#Rp;x&#YS`N0XG!?fz@M4hSqUk0gXEvNPIv>5?lxyD63pY-TC?}i zgRqW{weHi>()Grrqn1Y!vLUBk{I=7m+kBHf5Qs&C=BN=r*XG#p;I&=VcO#j2zmvtG zC|K&K2Add*CY8TG%WHloC6i>Z(tFv?V2ffO&>%{apb(0O3o$5!#Jv=*R4Ro})@Gn& z`w^fJPX^!6cYfV*cQdx;Vr|xev;6tik+}?cz$7yc9lJi6tgxFiyH1(XgqOE&hxqWX zh0jq5ePdO1Zk8(lcdG|7TciGyq{`R)09l#qO;0uc22aO`C#p;Im@y8U#%5y*UqN|+VvqtcKZbdF|GN%jd#jLbOLTd{nejv$VY}bNS=&Lz=L|AQWWqusmjek&JH#s&I^a7?BzBM5hR*kJ zXa0OQl5k@OJ2$uC)66i*O)oaI$ZU|4)o66r+d}oftG5tRagUXbh}xLQI?BqLJ7k2q z$smOUB+2DYt5qsdhNMQWbTLMDkL%;r#>dV2jGH_wH#hz1Y>7ipuns5g`=YO}+tMU{ zyUPWtPm{*v0rqG=72TXX7}cP+gB;rc31wt+C8DdVyrlzW(-^mtrkvtZBl!j5xhrxJ z1Va2IpT(CAI|kKr^A%q#(c*S+32mr``YT~>o=-#7xKd0(N|XYeV@}e&(_TrIvMcFW zRH0nx!c8$ERU&Z(-ra4c)EnX>-cnAn(sq{!e-8ig8FI~QQ2k;2(yOKw&)C4xY5Ob zdK7;)PubWlpSg?b-#cc~&? zx=ObtBsAM>s+M1v4E^N%rL=Xx9IO~q(X>{6 z&X!JEZ$LNdrvcJt#2WR>UER!SM=6z{LKqodqr)muZu;PGIODj{N-4Q$=O0)*My0}% zouIG(hU=$s#VyQ`*G1Au0YPiX2MhS7qZ@DhWNkt<6bq&xiBV)56yH zWu~DWqI>Li8o+^A_HS#w&hy3=T95iRb8HBt{5g-fwKhG>#PBqy>BxE zb@g7((*R3duC@j~AnMWiozz+##aLm}>(-r7TyckXlI~4Rse+MKNh0{dq_%Lj#5Sf7t8f-N@wl!(ccb09)f~rmP#!9gFx*BSd`26IYcb!io-icv--kTGa=RQ;PDn#l7>P83y^9uY74R)A9> zX3x2?G1ys5BjIF{YVNdryqKo``>W=54c_0s9w*7EnjW-3V1DnEB29t_T3 zr&6bC*blC@5>994Vn&OWdlyU$7vaQ#`wR^P5gSBL&}}Yf$}g@j$LeU>s~R8U`$4Qy2=b6&wgwbKpx4C<8Qbwqq#-acE0xry7 zPg9Jrb|8$9lL-p+N85VtK9+C_i2d3}p`P(=4E36!I2mbmV{$-%kHPBQcE8=V7F{P= z%yFV%;C#$xHy@K});$6Xsr}y^^eaENouBMBGL8t{)K;6FVv`0$=kM}L`pNCj-vqQ$ zt<0BoRjCy?mpNQuGED%pR~Fd-qrLK7^lpj|Ri&IRh7VPvNs zu+jypfl=oK0^^oT=Ers+W~E?W1#NMoO-Jf7!6P-L{Jv!9^3Xn$-r;ydJxeWW(Fk?4? zfzEtxo(qezn^#>sOHN*qr~hedYxQ&EZtxIW&nJCrBswLcZN*U(Ez)`)A-J)4@`v&f z*WO(gU_QK{fYu%|*Xn{6&|(vpkmpqb+vHE@)HgY}g0M24{eLgKg_uVsrPx5^ee`+% z)|7#pyLEa0EVN_CiYr^>_QfQ6XfHlI{92&<=n*!sXJkY&Sco`v?znTtxXoq8uyADm z>{8y2*--V9{rNoyUFWl!lKe!VwvR_VG28d=U_QRH+j!*yFXsB+N~NnmwA43!JoS8Y z*Y*s2g@h{8=Nh`zIFx&4kavRe*ELjiSkT~QgZgTW$|O2!6M9HE*|Q3Mi#7W1sIt&D zwnSAHQytWqa_}53>VIX-yVfd<}O(_0#^N5j3J`2GIaaX#q%{uV>;-7!KibX z2`$n&m-D~KR$ZxB&VUd)Vfp?Za^&CIQykW3See7@`DH2XGe2PHLW`cT$BtV!#>&y7-DrV|yfYoZXWI+B!9y4$rJtJ$PPfzW=5D$I;G@ zEXGMSlKKe>SOemzz6K|H`yu=@ycJ3uIlYFU`WvNW>OaPB;iXq2Gn}>yf2(IVJ!j)( ziaPkVBuiMdI7#A%U-WoiPyFAHm!SNuEHwpQ>4r_!HpNz$Eic$d5jVrMsP>VN2Y zKPQJSRtR?S;347hzG*rc3hj<{d|F;({sC$@LBC^w%Kl*tEmdejB{xAyB0V^`gmY6` ziHO~}%(@FCu;w zT%Wan-6dx=s)KaEYu3YhR@sDb+#8mpG^sk8eQ*(@Bu|(4Z`3|2&<_kALW86_LR2_p z!qO626)Q)@v4?W?WL8u`?{6i)>wy867uLqleGl{(U}CzE+gkRi=D>oK8>UvXD}1?)18*^`^_Xi<3A|cXy~Ii-owG*0%bis4lEdFPH>>18yppH*>b& zCKP$9daDMqHVp3fV8`dBX)KQj2{;B&RQ1F;g8{1yX2BrXq2%c^X)uy+1O@2SH~O!! zUdONOBHgFXO_q|Z9KqD7(`eCB-1t6nQ>apoGAg`ds2 z76YYWC5q>l7L6ZE;>ez#+MLNGZ9I%v&Volo3aXo5%dD`ZGX&s6k8e4x+oT=l$fE#6 z<~iHZ^NS-5?`o*;x|Cb5JZT|42}?;=UB(}2hK!V#8s){xfps!);0uczjE?tEO!oH! zV`2=20RL-!{kL)IqmM~%ib#{eiWiwg9KUE?PTV7AF)e+~HQIC$u>0;^x&o(?o>t=f zQ=!!o7hX(B?(_Gv;F)l^8n$1`$Z1A~i{SOQnNJhCqGBW4DlaF<6kFW5T&zrxR&u0l zH$}J5(wU>FlZ?=@S$1|2(b$E zzCu-7$ig%)0g)l-7<-mM)!0c!!{raaekwzuv)_?a&wC^sUd=wvbDt%n-!{L|Ug{`8 zI?CMC#Hr$qxOpNr6zPbfHoH{(@}|LxesCeYIOn75uh0)%J8)>%?lu!V{hVoz2)jivP#q_=sE~Q(4GqgL3&?pqxuBTxF77^lfFJR~n8;BHs%h2=LK2}e+Em*dt$rB-pN?y!9a zX79ELN%|R|J(RWda7|s|-nBEoV8^I?hx&T2LYh&pDVm@SKK5Suv?wV19gX^q#1^EM zuQvF4B_uyOpRP}I^%3*)SV4%vAy`QK@BM*Tz_cHh1$`;3{rz#j2%XLpHUf;{Ot>8r z6CYRap05zFYtz+tv6tUVRjuyADnu_n-`1@ytGPJ2@z`jLd2yY4X!I*kodx!oGYUuz zJY$<6J?%02^jlg$quk8tlc<386_J!|hpTRQ97kI(12@h{v41Gpme%!%wL*5&6;qq# zzZu^8=sOwryZZEd<{VgmWg-n-Ah&2dMmR=i0;e`!>sCfEc(U4Xyfd=eqQDhOBg5T#>iyT+CWNf(xVB&Pu4qt zYRKI^_Q0fiP9oz>d|las<=MjBO|A*|K3w#!bN@O%y6nLjhJ$Ebze=Fj%utVvakUMt z!GyEkWb|4*Vap`PzxJ>8Y_k1^c`UZ8=zU~py5Dke-mDZm=!Y_YvqjJDH&MJ}HANF) zJpDQi8%=xev3kw%L!}fEqLYD1xzRx1$I);q*qMIgp*RJ>UGa4%ez;u>^f(Dm3@O$9QhH5_IQijQB04z8N^m0 zgIvun{p)Bf+P`0pq`>iZ1pH8*YNDvpwttdMgd^~VWW^+5Qgtk%K0{H;<&OA#s_+ZJ z&;1~MK=4uqe9N5i3I{D}xaN;5D-vzb@1`}vx75olTqnY_=b@ooLO%PKaScBjM*y|7 zxtw2e@Yo7(Qamdn=OkQ@Y$+b>(B1c%m$v-PI2D=dlTS}F%L=m-d!1;`d!48&rCSs= zn~NvTjh&^twBsbuX~%MT3wz`t!Rdi3ILa19!=AvOq++c>qV4V10MdCD;hb)v^a~8i zFAr~|>YP9xr00F`HR4u?7^SR79ZaMPe+(-<#0|PDuzA1}pM#na9|&N?nrekyu9rR8 zwNEKgqDd|iLbA8d;T3NMU38kU?Xm;L=w0LWKaj#{U$Ow!W;NK{JRlHQL}}qb6$5)N z#5jGJ%B|{0HnL^w=3@doTH?ZGa_UQO@W?Aaa(q(kYp_w_(Y4eLczM{;=+}tyDoyLk z(!IyUC?ak2#DU&rp@isxaTh!z_y@f2?guXjInekGvlg8vzZ+q^{6fM@ zIW}Xw4Ifl5xgcxDv=W$^j3nEolMGWTVISklv)j?ePtP8EytMWhhwlN{E|?hD6XH+P zf{aRqq3^JLff6Fh(M-@_%r7&8!Js1S_4M@jp#$;NcMExrPIuEfjh7gF(RnKi$u# zlonjvJtLmE@(ySq6H9>Pe_xHh%h9*-i{Ol~{BJplur`!vJ+ODoWDy#2QNSJ2w}?gT zOR$HXg;PnieTnNmiO@ny=g-);OKH<-{ zPlsvaHu}0x35b=J`zg_;w@XVRF7h{u_6i(82JBWMlt2Hw(W7qMya5NO%0~Z=|MM5W zGfo$)RHb6TG=UKl*N>qs+6hJ`lT5K>zUfOBzizK8$p-D<~c}C8s)u(D0gT*JrH)!oA!b9pV_<{Zz zOmu?&65`}TAr_*&KqPsyV&((M?eoZx6>0_{yn3nBD#UEXAbY^`IUR}8*(0*GtYiF_ zqLl?Uqwtmx0}3pZ5h>rQ+0PS;J#7Y%GKPqSlN%pEExig;8-nu$_Qs6ctzuSe(tk4jhDq}L zz0+4;@=b9e^jlecbVukgZjY4zB3m?YPUVcrsRUlIE%z9LaM7h;3bte@`o_j&4ooPB z4I%9w@Pl~=`uY_xL`tVRiI9-m>a%Z~7S)!qi&HHeL_TQ2`U#MTz7d8d5L63~VG?l~ zAt5Tk==!=}-nD3wfNN~pNU&eKot>Q|HppMIFiYve2cvcQPCMHGg!B4U{LN=OG!Xo2 z1^J8IfP^`)jc#ArWuNbw9rmzUnZqKAQ<9Kw-iF2Z)NT8m7>Xzpl3=LI+;vkbeNYf}Ye}J}_{}Gt4 zP1o7YbcWeaOMDMQKoJ6t##v(PJXycpVf1~OKa8#}Q30;SDg zM+|ZSMiH;nYejx*nQ#0U!oCBUIHW%R5W74-vgvI_N$_Bf#7W{^n>y}$FLPjXB2i&r z7{itQIw>2vW#Ies+{I}7*apphaaLSl^f4tzZ6aR1o>)P-u^i+WFU*iA$q@=uY}AC- z8`rGV7!If3lqpc%d&KvBs_8C?ATk}#7}yK?!CY~AGL|>i2(YxAvy$AcvEh-AKlfc8 zDKkuhENGD?-*97C8^mLtjvtYLm!crqMN*Eqo{JbvyU@I$zs{EZZ&f{}b z=$~#96gAX2w~;Gn_H%z3s8Lc!>=I|_3izS?RPX;w^&P4xKUb&0<{TxAARCQ~;a4HW-)GAycn?I{cEIOAq5I-yv zLz+2~V~5*rK4kz`4HF@OlIJ{YKmNN`p_XQwptTE+XnYJ0ihb_3)=mCmEMSyd zqnS@?I0S}h4S_i~=o1E08t)^2dm__3J*Ct{NR|mXm6U87<_%=34wA=&)&TWZQOR?@ zzOwM&UWAOB0{xg{M&AE%H-M}QunCf(1MD6k_+nwb|KsEbw0S+!tirl_F8+gc4=$_7 zlC4lX_yyHBhDLN*H@6kT0>9J^5{ToI1)mqb<9*3o5Nl^CEzuhEROTTZNgH^XaQcx= zMXrU}n@>ci4y8tN<@e5sV&?lV?=)-c($)7m6m~&&!Nt=%P&f%8Slh$1ji1+!NEtOg zzqGZewDoyal!qfN=II@Pp8|L_0Dry6-kM)W4`1H^7DK<4>-oAp!0g{FJ1Gon6*v<# zL0wLg+~-j0(^VPiYh+}d8Rgh#fRT`_SaXDA$OxTUMJgaC0EUD7?4_zVo@WhUvZg>W z@W%{&yW`iX=512Y1idx6aAgWv9vlm^%BP+wT7yIe(Dm!%`SVph^s7ae4hu(pwJp#}^Irqzp?1-nbxhrfm93d5favwX%WX)< z)v=STJ8nw7x>I51*p5>o;aBAeE+PKNyi*TUfwheffq#_phe|W|31Ufx_Fg$woHIq4 zod^cC9r|h__v`DgxF{zkb2?HG(EYQ(-YVw!bVUb!fHC&FB0~f_&Rp%z`CsoPI}-(;_}d46*WE48rx5>>z2ZCP&u_oF)^MjmbYNbH@(B4k^!kaxvH6 zP5n28QjQ!dDlBLEJ#9AupFiY%Q;0aql{3&R2I8lA|E!`_G%Lm6Jfn$Q*n>U6*IbAo zV*nQayD5?P9=)DJx!3{5P!LD8T>|^ys05kEcoysW@Yweyq;h|xXw@b(9X(#6f8=ox z;*aEEZcVID6D3rnH&_bhr^na#GMh(oy_p@2vijVY%umc;(n@#twf^;nL~SRK!6Op% zQ9OZr)xjC*l}O1_1DE^e|G8nO<(}0^k6|ug2FCrS%kz^%osCbHweB4eotE8E*gywP zcSP6#V8Qy#k%CL#ACB^wGRR@S4C9nX$wawL9sNX7XBE6nu*>og_xpNPbL+=Ia2I?% z$ibEJ?EYn6{fH-BZ=~e{#)Ab3^~+~Wgreg{9EdG<4~)S1Z=4gKCPSJ?puI+JxeY>` z;MtG3J}Yc=U*fNn!S*uo1(^?lxwuPKm^lpAdMdi~^HrXDL-J=;{k zsy5>*h>q~vc6Mzp@DI}_P~D_MA!klVd5%-_Wg0MjB;?Nlh%>Zo@aZ^AiCDF8@`=j3 zmfjX4aB&n>lo4Y4T(Amso}_~YxQd685IUTS_dWcF{YVU6v8=tU1Ux~zCTTBFhF7J|Q-0Ol9L zV3GD1yFcC9l0+iYi%=F)#@<~UYMi5}kZG8;*U;_~oVC``$fJ(;&uXr;=}TcekB zp_DQ&T%qR=%~sb3VyAs?K6qLVL#_Ta+Zo}ZTBSa#Ccd|9xq#hU!UUNx&oQ!WUSle~ z$(HwaWTNfrT~>z>`dKk#<4DHzSOl85y8@{mVkEB{#|daL0<^wmRoAF~ZLZ$TD{4WO z^7WOEwZxGaghSw1cc7i0wnNTBcQD1dc0yjr1n5 z!d4)*bv?$H4?oHM(-o-|$QJre zC-h5#I0;&V@h>In>Zv0FT&W_4kJWpRPRJY@4_HuAY15kT+rILakMVgkq2}uzWvO5w&n>%>QKWtxIs`Jt7u(%1;6J+=n#DT$YqISv60{= z0!fgf-FRG}{ul%i?itnJrnWDyWyRQCm!DTqA85#dS?eCCe!sWLf_DCr6|q z%gg7ARAY%6r6W$s-p8oL!C#eDw>@l)NwIK5M9VJvgW^a<1TS2qL(`F*)sk(T7w{Q( zY#Zz>1v2ib(M66O4kBp$*I$*idf;y+Zlm^^E~uCW=72k3Z1Cn+cwiygBd`*_^WE+4 zUN84_`BHf(1O{k;)Y81+%DDvuxapxxz4N&F^rK>;MeCZ7Nt)zIxzr-FM0R(@5f2lO zW;I6EQPQozdD5a5L10GI4cA;PmJ&QMbofCBmR3fSMMb;Y|a(@Ij_MHT0ojBb}pjn<=9G3 z-Um=+sjaX9cY50vS7+={tY{u%iI)fpwbX7mw^w#VOzQ{2&Wzdi5;DF#*&8Wo3gaPZ zQgU)M?D5bzu=7c)u&G$roY3Ys6hNW+M+rEAo3SEi`XLepk$)VxJqawQD^KqPqYF&Y3xz=SP+FP<~tcSk?q&gS*LxeX+Q_rlgVDbWC7%#`Gqv*O0Z>Z{;w z-V%uq4WjGKQ=rm(g|r|_se+eMDo~uNvPkjjgbPdZBmqD^_;B`;8P@`H)(FKy0b2XBs+;&)F=IR`+!zoi zAMU$v7_8+Edaqfq_?szXH-!o8$vDw{C#tQw;lW8qa=QgZy#fkiaa)|q{$Z05b!)_d zYr_1o5qdEwyIv{~$t(`pr{DE>Uryn=NmNG>g$&d}UgVqu{`!osjyAmS5^ zR1!!X4Sxt?P)BD1k_*edaHC-rx_x%{B5F~}I<#hz9;O=1_RJ;a%5O2Bzicf9Gv+>b z`^x&0K+Dv^(&qVr)XIH4b~{4rN?ocr4sXalO_prqs^tyUFX+0?U@uwan_UD-0M&7b zJNfY)O|Z7Gu>9~v+7wfuB_J{imT`kZtj&*sZ-@y!Y2eWd-OnYI%i#)NO^%!F_$XP> z^}O%>mMkS1;%ZMq5No7aicIW{6>P|ZI{ZnH&64f>NT!A9E7t15rzN6kV{P*H}bXOOyp8=)@%o(K{FSNe+wJ19SsT z7nO?aIieqHS54Lzg^&TcYOO+APoAk9OjSBFEr$b{jxfkp%0#v<#8relMKNuU?04C5 zbV>NZ|Ika!W$y-k&q{*RX8zc#R5_;sUcWQwK*GW=_YMOv#`gA3GDJgA2L_93}e?b3m7$QU*DhczdD$*+Pr{xKl|1KAP+G=>Xp&T7wZqJur^Pdkf3p7oZ z=2BH?l1mAPh`$-LB0NV~YNbo)cs>7$9Vr*WQU$Ou>YbrCQN)7D40#8GB0Sg36MVN%vJX#34~lJS92P zyswD)f-L}(qCjyFKXNuc-HtjgQVk~Yje6g~)1;`g&Y}C<1sPd-{+=pp+!p4i$vA64 z-LJPW3iAk&mAmA;_`SO4#t>4oAxG6f1^uN(DjafXh#=_k_;GJ`g2?mD&di74<7kqo zeMzvu$uP?l1)yC0ch9DFC>8<$2cr{p)LD(596Qb|-;uO7+j5$6TH2|#a$ovEc=sgr zr4{SLx|=;SIcW}hB{+oV;8-e>r`QYHqluGvW1INj0vOPFCeV!U$?VF0Y>o2Co&Y8kGOcx>4HmuYEF%YNoJ4KDxn2|B~nNS>3Wf!ZOy;Uood0Prgo6MweyR8J&?ZZ zLZh~sC4rx%8iP7E%eYzaikES<$pcd)$e_k5Rn%k=uBC3!KE{jcEN>{~DRSLYzJDGg z$gOEZ(l-fnq93Q)zj>}dJ+-pJ)D)C@xHX!-8v6h~18&`a6DtxVqo=fVL^Wbwf%(tK zYc#h2(F;8cq%FXhPbG0ZF+5R(G0{Ubsp)a; zFMY_a!xUbc$-^~32CE|CfMtQcfGr>e?5myk6jzkvyix!+?l+XLLDaN5F71y; z0vbbu!f(!8XKGlYDCP)Rq{DEqnK#I+K3jK8tonL~jv_x4p+ow6_feWqKzVUvr&bmo z?uc-uGi|&CBBh*}klNZHJoy8kHI5&uQT|if{=;ghKY(TJE(S{L7jADuzPg9~*ZO{_ zMcw3>I?&J* zr68JFr0isi0~(+w>0|BU9qc}0mZwuETE_Gqv0uruoMi#mK4QLCdjs8U>Q-B8Csy{H z?+16DoiqXFX)I=fV^E{<*`9nsjh~O5ma|>M$SpJvp_~CB&eAkH{f!2_|{Z5CX-1nkF&`|2{tjTR&b}!D@_;=2bOEP?CY0#ffXGEygIt4J+y!C57pgyORyT7|n)d>N4(htd zZQ5ZLHw9@p1LPpkpXr#=+|W?t56Al>xzpIY=onbTSCkpst*kmQjHvk>(x*TZm>H~U z#WWq|NIred*V&)kO^9Bp!~LJ=?iLnDN8?JtnSh@2t8fua>C9b`KYn+b7CxT5;>EvM zIm+pT_)IDTjDahd#88;u*QD%!WFA2Jx>58)UMYKSD@FB5vl~{`Js)?;s)>)@I$8YY z%u-_P&I<<|Y`VLZ*^Z$p8={VS0|km*K&1S~jZ;ArZ~R-e49wfd@pg`nPa*-+5#wgz z$vu{sbaMY^M$uoLBn!;@?E7&;bGD*Maky?-6&bH(8IL^PuQA&lC;gX4^43ZZoLP*5 zELOD(q4FvIwUiw<8q@I!05rrf?)gIp_65t*zsjAL6bVXePb{tPU{dUap`R$AKLz#xm7e!gj}6+8{EZkxA~9=HZE4WMhj=+sWq8kE>+xC1 z;AA6BmZEvxcXkoIR+RNP>wQi+O@UhXz0)u>UDqn9aE)n&c{Q=%VomyzaB&8ka?a-H zL0de|1M5+EIC~RoYncclbI?c`##s;SBHrJZs^d#O=R-CtoY<8nqyL!lM87g1AN-@( zLSJd(@t$eh3Gdmo>c;{Dwz%{SVicxjw!U~1hQ?^+8~AzKD*7eH{g|ATyBNNyL zUwFIU<)Y0lkM5@RAH7H zA1AYMeRi^J^H*W8DKt%kcpr*I@O?bfDR~Yh8{xNh)9uIL12pahTd-rCCK~AI$^xK zZ%pn~wSaJxRHa6Zg#5sX7c;cx_=DPZF43&v6f+{P@2}S5N-#LVZozbJO`rA7Ax>cm1mOv;lKB8gPgeQY6$tEjIFdnw8cb z=JAx4)~q+@FYjCHl@;p7G|v z*zN0qQOTp8S($M%r~P#I2Z>Tx?S?B!pmJ#fAZn+qI{`_lsdkB)9{+P9Wl@H#rc;7{ zn1`tmQ8JTo;pG$aj-Y})a`a}-#e!bv<2NgUr@;)^6xRxYBo@;>JIV6s>O|QwQstSY+(v#uDBlw2R)e75J z!4DcmfjjuD26qxG`E`$H;vTMZi8q zKlhw?=nBw~q8?ocv3z*@`uch!1wB36EC{#m22EExC<2-m7Z=O5Kw3*Um1+OQv^{@Y z;=2MO+P!IVN&Q#m7bKv?x^bStEfpFa4u~+mAS=AmwcVt=HXy$kvYL46&w2%px{1zfpvv^)q$A{tdcC-g1NWG-EBPtOSgZQj)Yd&i+ z=UW=L5GBnT|9EKE_JP3ivD`*@l=G~hzSLFq&cNjZoTB3(d^_T4C!756aS9h~gf!F6 z0hoJ>9J;BIAs%knAq?M22h+DK1!sc7W@FNLxYvw#J-$ENz8_OO6Jj(40rruHG*yhu zaia&)=e9Q7*{>>exaVAM`q$`9(HcxpJ=8(Q48W-a90S#d`}_Z%ofkMXV~s12<8ugl z_?`+Fee>FUnIn0a9_vC&cMHo-zFrq0?lCvF7&Eu=1pa15fp2-_A-UIcq}dOLBQARft_HqibZ1z9JyIpDq7-v^zgxbO4+98c*5@*R%2 zTDKIBYq~FAwSQDvjve{496hh~qIfM_ua#6oqwzMbbK;)o_LC86D$pe;R<_Fp-#$}t z9IMu9Ah3%Yxed=P_pi9+GkyOKLI@spEOxFFDOF)GZ-=SGB_e1A1cGuN)dj>L|Js(|++WTRB$blWM(u{8?kZN;RL18#ViFDsjF67Qi3QRA1?` zE&)8DL2YY0t-ICzSGeWgPQP2;yFJu~j&aWJ>Id_{Fv9A|<6gQ~uxyPPAWFOnW3I8X_R^M^R4tt00q`&9Mq+4N+w$=MppN`7=(~+l)q;znz*w@v zm;@Rl^)rY<#0Hpq346&cf_+l@LGp7wOyk;u7recdW*(baH%B=dEoNiqH6r=i#o*HP zF`~~(ZX>AXh7bfTOORG7eN1QX_-nyt@_v^@HA+SRFW&l($^s?(Xw2GWr&(j)&J%Fz z3HXmKmW58!Wv-CltzwnId={+E_2|_CWH#0gq4eyZ_m1gTKSOEDB3XT3t3utGb4rr> zF8BN4VK&yhNWo~%+vH%p>)qseOIIi6I1wT(td)+I*j?FeNF*;jekc5&{k`wIZM%7H zglOT~)~3U2wrfv{V9n6^HC3_{aXC&ZfWTLE>n--Idbvf^UDiLI+7NZl|EIy4eRxRK zbq957(e*V(VjXq;VF6G;`vJYvyC@7Vu~7qN0lZ90xW9qMXYT5ty3$YG&KWWJ+V$rw z$9h|N>XVL1dP{2GZRJ*Y#J^YQ#$)N5OJs0S+dV0VpWejyXl|vyP&e1MUbkG5lFrPYhCwPeoxeCz|T^9!$>9X}+RG4!t>*v9|Zj z{5dObSKsmk8j|igEo{dQoiDSwF@#3kdE19Du&Dr_6tJ8atFweqT^UwH~itvG-U+c|qkj|=TzBR5NXL9!5 ztDeQ*bFE;ROA9t$a6Nq8wQjlOCL}42$7zK;q`jx}hE4$X-4@xqD z?v%5xIh`V5q+Yl$nS|c=KoF2O0PWMBK@gU26!r%g2c_~UyM8_xY7d&i8TX; zNr|Wk;{|=?$l!Xc&{mpTOJr*(5cJ1W;-!+SUc*A^l23TwV^wQF)QGB{dsFJe3gCpp z$KFg}oEKx(LrgbxoM0!JeQjFm_ zu&|q zL6Fi@-J6Bfj2e{C!ou}GQ6K!}{WGQf!VOseZa#f#bA(;Yoq$gSzB_;#q$J{s{Ocxm zYSV4YHE%AWUp3mC^+$TWe+aEuBK5|!y|1nO&&tXe7~qsH?Q12} zN>Fb+z$dT)ZeEqmt>GeRY&0|SB}X=gApeBTq~X0kVxR!k+Z2nRC+5V~?a4R=s{T~J*F zwrUG|x}WH2ZLkTD?_;B6L<-p!77ETZtSoH+lsV!fQnE0f&8$2uSyYt$KJfpJS z-#ZFBwl`C@3m6~*iif7;Ert?SZeq%lqC|Ha=A1a$k|8h(r|?g{{lZpQ=7A+hLaQfB zhzbbizaPaVC7#^f)jph}c5Uqwf6a5h)F-mLI1?~QR(1RC&O<&pBqPzT#zy0$v28VOlJC6k=l$|O2WQW$S;v|=7t;*ao83mlMUF@tNHh8spLegm zpm>Xo@g`wn4E+=Gl^Up*3rNz%exE!;k>y!agi4YqC68Kq0Nta`fDXaODMG&InerT^ z!V9i@*1t0{KdlZV0u^tCvc4RoX|^e(bvH8=7>E(sZ~hjNX6@V6lu1cRd4^*2+CkQc z5@ewR1NqW0BNlYUm=3eRb-Cr_zXu1C<_dib4@GW$IQpD>% zbWQVcqy&jafzsY=Cswv$CbtfHm}*~ZC-5|#UCF|Ripz+ZW6cT%J$x+U7OrmBv5>)_ z!V5Rp!GhThz80=#25W;h>9(ZZ`{$58V+)Jo9~CGtK(bo*w@$uRt5V%I`7b6^7AJ zasASgJPD=0nF?) zPp%7Zyf`-@>P%0XBUFo}t}9d@$tx{nyZsyg%nGsLDK%ouPrG4IN6K`t=a|#lH;Nm0;X|0wnErx+u z6zI7Pv2XvUd&ZyNE<-3Nw-5nzh&%m|tDB6LjpCL2 z$fJ>4Jxwnw^z9P9> z5X0)nFHP4-A8EcR^|*vTr2iL?_~EBdkPs4+>fh_V1}_{KgUllhZ^jZ0d<}&Dt%zu+ zXmJ*8&U82@6xORGKWfmWSilWf7`p&^q3JnPX`oem?O zn^@4UpHpIX(-?Y}mu^S#KSq1$bT` zBWfy)6m4!>+kcwa{jtX_lL)*LM(bA<0W$$v)@BaT^12y@&i`N3Prn36pPVVUF6Gea znvw2h)&O=uj=ATzWj{oikY9DQg__Lp;IW%j_w$-r(+K~&P))$LVL1{i)Qy`}sILUS zNjIffZB;pC+Tq<7+F1BKrH`xW+59+rbr`Ujray4hNke4gu-471tf3-Gi4uPn?ww00l!GYRZ5PlI+iSHYfW`V76KcRNNwjkZ|B>X z1b6`EuFcYLYFuk#~B zK`u^Sd<3LqMBKw$S2u5+loilBV1AE{Ml8Rbk3K#9PREVxJpzK8$lt$ourB^dowAaB zU5WY+#JnGk_qmO+j>;@L3@x_579DfJazD37aW@NrdOl6LNb`w(*4;;|32~wZB9c_Z zPPE}rtg#{|cXtMKfU!F)Wl$hZTl*hdj_vBrf~((S0_~H?H?dr*N}IdroNsZH@DaF0 zO07`VJY2HY7&bj+P!oBawXeZiwaSS_s)#SDzq#(|GY}&+)owF)#Q=G0(x48M3tBW-Cc)l6&BeoV@Nrm;#rEB7647iJRExS@p|Q7Cv%`L z^NSIvlWJW7P!ef$K2&=1W075KJ5aL_9dFWYsgdNHLZbpmeA{h0b&Y58WN*^?HxKR$z_uJH zu`alpb&+n_1-G*j#rCvcuxAx86D`k?dj}^6>BsU&$+AwH;!5)2ZoEmfk$#SQ@!zCX z^591YMbFnD>>usX|4^1Dpa! z&`T*njE~<{VM)eXO(FKwfGIM)BM5ze|y{ zE#&Mc-s*ZC2UMv6!iZ2i0^G6|sDP0sHX3yGwTmStUHP?Dq3!QzPkYG?Om0I%)>9>l z$KSGk-5sYuEVvfxmtf}DP9~XKr`T5--J%h6)vekQWa+sO=JGUZra0;$z(F~tO|TsU zRa0Scf=Dp#3D9xrd(L&a2B^5mFe4$5Cl%Gv!2q#iJTHuz9cL*ASFU9xAGUbQa+gGtpQoV?w|fMWLt&Jd4=|F(wK$85DHY7CKc%}iXO|H=3`B1GFEUvL{0yDI z^wN?fgeYo4*K7MoP#I=688lPL5p6*l8ch{0K>L@5@eaC%0^GIjV5O7HnVI9{c`4TD zKj3FlH8VRix5`CBJ`3l}I67&)qG%GJ{`WlJFh>Mu)c>VxQ=1|4gP-P_wzrC|(&JR9 z-t%vGGqXu_m(3la5Q)><{CzVIjQys5DSd84*^H z(1SormC=I>_qsvr@XwCH&Tvd4jfJ?8c)43IwkGnR`pZFJbQd^Qz)NHn8z!fm@SMPc zjAMgx8`o6-QrOg5a*QYdfU~BYaXy9|sXeGyoP`iEY#>byL5+LNe9pXnX1KGj1gcPG zVtA0{IOTad#hly^-&&ADj4_;tg6S14Tk2eL{10-rq8X>0@7p=wjOdQ^V-yx|b;-Cr zXIfg}(FjYTG?my60xmz~JN>?W8hA&VB187%9!_@*_j=@LZP6H?1tLMupj-W?zjY_+ z{&1qX^C1vPTZvy0T!I!2k^hPot7@pH7k3lYtSO1^M6&r!c|ZKrEuOP!F49z!JjHh9 z@hM-`Ha->O{|utQ95bfCjFXh}gpunMBtGWn7t@=^&V`u|V*5_wTKQ}vDwe0F`BM0I zpii5u-F(!dqQF*y0Btxhh_D9w7HF`w!|m9td&}}6IoUex4|IBvP{Z{c6Q|AAEc`)_ zIVL{ljIPLyi5Ov%nq{F(cVJ8d2LYD!bJ3F!ajjfI_;^p%XN{g5{Q44DSYj6B!+7l` z5vG&>!%)>l-(7=_HcT7PFV*c5i`UwGA8Sg2FjlC<4Hr;u>$QU0+1g4B4EwBcewU)) zANhmYhGybeLMOwpG|Bt~4_0*2_Tp>Qza-gWxT&1D5oX*XlC_kW!k6763hspUzZmST znMWm$pU7X)c+ zr$M@^&(;wuInj5Z7##Rt#K_Vh6I{xd-hgf$c6^kGf%ntn$B_sbDFHzWe$M z)|uyG?XYJAhCEwtTUARYfmP8>rpPxUY>1~HWLp9cBT}3MoUeZNA8IyYXhYLobg5AI z)PKx8YrTKronuN;h1I~du-N^L!c0n5u0Afr3YD1MFH@q5=OJt*24SVhV`3U zY3Y#c^#7M4w4H53rW+dLK5SQWUPJc}(kxhm*xP~#)O5$ti&r!eg!IrRD^jx6>9H-v3i!sB-A1kb?Z zc!{8Ps(8LSC#O;Nvz1N;5hpS^+Th-e>L!I4Kam#-Dj8Zj|&7rt@s;#o^| zftLgP>qcLS@G^Af{}v?rJJ5!*Fer%?00}6}bG2ptEcTWI`pt);p7I(RP+-YSp7}BYT-jf>JNA2jfA0G6q+zOyzX&O9OhH>sARMNs6oMxkZO;IX8RX{;MeAPt9XpB{c!*Ra% z=2T?pU8m{DR$=Rq#$7kRGzf8BbC@^>?n8ElJ{NKi_#l13qqdFXoR@>b zq!yBxfAhrL_@tAm(pmvH`qc8wu(B=8vH!q zacU_aca<4+>T1r508kjni_qqnDXnVO&Vui zmZ7O*p3G^m^4}S=Hk~8Ll>hh{-Eg^)p-0M9X0ZsDp%a6}!}ZOu(mqRyk-5WEA$Eds zELu9*TuPu+5Z=e2PXWXeuf}i}Wxa5Ar}H~;nw=TpCu=!w_{FO+m)UiHL6W~s3#K+q zqrAIQW_lvp^&M?s#hSvG431XO05|BrOf#6b1iDo#^8?HTSYnk`3?16xKmOnl0r^** zxJ>()s$<8#;DTI>K%_uZPUq6mylrz@u5W+26$LIrXO9`d|EAag8>QIcn2XWW*$#wV zg@;<%NS-rR6+7lmD4UR2uHAn|zAtp8%)(7eF}n@iY1ZRlJ8J~2gJ!`t#~0!@XyTxv zvig9lz5yX>WbZPc^kKsb@N19$by?uADt76e{@qAc%W~cceK!l++!}>e8BF3_w4*L7 z_LWo86%`eK(~6@=zfDN78dHVq7BapA4EmV+!_BQS%7XxT&|CJa4=MRwLxz=N^CFEi zo?TyWoqih3K;378#latYtXV1!92Ey`^5w~DpHY+LV}WrzFFg7VkCh8>jdhI-nWBZ# zf^D5Sn6!DxWeM$Sq^DSR;TYjtxzMxu4@$>BOUIkPms9Rz!xa?7{s=VbFt4?M`@dlT zs1p9*5~gZX-Z3~hbHe^i+%*(xQ;lz!>tt^Jt;?lv4i8*Ll|`?10AmSue$Aed1nb(n zibmNXhKUriB+`j`%W(fxrkA6FW1QbUG=WLbYhJZ$oDlG45N0G9Q$JnEVAH_HmNZk5 zH?V|WQqeu1;H`8|n#7i&jMo`oK;l`XEN4NNRJEC*W8)NM&xxi|9Wx&%h$I$L!X`(i z{TPlbJ0Hp%^76Qdl@di#a%0gq`FyX@oa+26%pd7OzP8sI_kj~ib zQfY1q!2~}hysydT<_>`$$D7NQ19))XCuauEd+a3^uNk~6B2 z;Soklw;Oeb>otkN%{CSrsZXZT)+wfjTkhS?5@M)pmz&#mbNXH=s0@ecq7O z*igoCo6W&upEfz&bM{e%2pCt7%SqQ~g7J@S&aa35ooiw4szqC5Cc;_k1tHdc4Tfa` zoRukr8RSYCg|UjMmeZO4IOabC!Rzp8zduh7YOia$NMzuqg_`$vV#*b#U_K4H@H?>u zzX>us{1d{(-Rky`1Ns2~9Yk&fy(PKj4-TGlA-FjO1vv$$%vfGB)TZ9Dv+ZM%acZOkn+g)V<5$d+(nP%tf6^#Oi^Vr}hx{_#Xd;u_ZVp3x5aHxi}4qdsSOincj zG~n2IA_vG)&ays&1sOiaUA}I=z3)ls;V@zDmYPS7?3vv>E#rKsW5F<`g=&`*jvzK? zy0Wkk1IphALHFRg70y(VC^MAdh2ITw|FZSFuEVLkhN!Aicpak^e)=Fxx^G{gJAa*=|uLgs49C98`J0r!$rMcsok7FNfFM+)0 zgPPWWwlq(H--L1rtpr$`EZo_~&ED=RftFBg2C3zn@h2NlvNTJ@s}G3Ir+2&|=l`7(P21*F(goyP26JoBfL*ei?L zB*7(nB^ru@s`ewasz80QD&`35cD<6^WvHyh`+50o11$~OW=lcgMW&q&K)Y!Tnb)&7 z>of9m(_!S1s)|Q1bD?U(ZcX& z>d$dGJRTJQ9!_0B55gR=Of_IQ{w*mt%4h*|G5Qmb(s}YuiE+(c0q-5w>2_gXZJ6Mw zi`?ZCF?p$^NU-&rf@A$!3KDpMj*khG4)naK3#dtwU!9#EO_GLo zt$%U>Bx*j{mmCqTt$H&czP39e)}2uwW!Ugz=u8Vn`vHb!}}RIJw-%MOalEG**vI>8oyfeb!K3z+d*PvxTkY`P6-m| z`vU~r2d_)E|7b+t&2!YAr8Tef;|#S@?hI^*)t?AKoNS4c+h6ItGE+6fYITK;sJ2#! z$2h>Nr;&+KA|j(*wAE&qN@2-u6mm)?ns5#z&{jeknz%?|1r-g62YnuFmj8}#sN=r~ zG~7>e@gTytMZ6h00ei$2S+2Oy{Iy|UA4x!u^8W~#T@y73`AnGza0)?7`isPv#b@Yz zO)z`Ptm3@rSG=Zn4e{-}adt4wFkW#=tTr7@f;mYG&7oj=t2?4^*XRtl)BAU#+^u%6 z=|8QTe;YPQQ%S#QI$J{hpo$r?FDJS8$=aw<#rSEDKAlI8ANSH_IGs0fRP0n~hA7J5 zobfwPE%hwjZL^83kFki*#MIeA^cSl_?5>A=kz8gk74(2oQn zo-Q2^$j1tD{~VMkas7aMX)_Cu6_UwTWUQhDX%mjb6P>L8O7nM4PWZ3_gA@I zxpM!2m$HyL5z^AMcf1~G6#*S^>M&!i(N|E^L?!7==1rN7oA(j(Xh#`uaqZwQ;s%5H z`g<~EAB)HkkumP>kZUTd=k&7H{W1#^m1t8|P-QpWAU9KoQ-)xBpY$_?F4lisq{&DO z=Fsv2;+uw%B31Yg-WtDeLdDz;B*IRb*njB3F&%P?sw(xsFjXC|^u5R2e^2^4@1yDl zi!!Q6sT+M4X|J)6)1zjARb`GF`(H*5%bJ^cvs)@h^eJ*V^ZyiSOv=C(Gp%`PIp$6VCh%f>F}6 z^0+a$bKL%+&&&0UW)lsR6RDJpGIFhK4|1O*e73aCsBFfLGf&(F_2BV-fI>?aF9zM#@Y2CEi{jHHf)=pTxORDub; z_$}Pl)q)P}u4`jxI!Jy2yZ6oxS`}Hz)e%>LTY??@jhaY7&4_ilV{$h$Q)Ch1b)TQa z==RMJPa-1|Jc>}SNU1?f5&KXi+NW-MePEhLF`OT2SAWIzNMfCmP_m+5Mq$^|2?`;( zme{okkuCN?Z{c?{eh#o}Yjj~&yZAu8LsCnAlc?kZZE=$e3i zvn^+8{IZ@z31^ucuSoy)?xn!K`IRZyEXMmqL(*C$*;h^?L!?kqt{q`0HdG(%)zrBJ3Njo~M7ZAzu?!YtVw*K8V=B%mc)R%F?cuUOdQUHZW8{v`hic z!2y|}6k{p-qv(0x|Fk?%_q3xG<7jX1!s93_2^canE?KzSHSwW$*(nu)V(EkNi$hP` zB06x>k#4LyzP^@zMr~X0hcXXg9i2I+D*=V+E26grN=9r1Jjip6_#h=xy!!aQ`1odK zE(v*TLwL5Bh=PAuo02B5vedw+n^xiG zcFM$RXm(?ZIl@qNuHl71jlc5ymb~tU-Pu$uu%n@MJ&Y%mqW&ud_W6ASTUnfnTHIqO zqa;?Z#rf7<>9-~MvEXBNoGf7N&3~+$Wn-O_cXQ%LVJu+CH|75XS>k@9xPj-issG9Q zoaLTonMmRN;&p|J3L<=W`pC9%gq^==nW9Os@*_E)%nw%(Rzys9Rwof;+d5S z7u7V}tYk@0PIkEoMXv2~r7$aAr*|1YlmBG^oRf-@L)B>0V4GcpG$_{Gm{%5_4s7|E z=J(+saDl1!0Y4&gO~M^%Hn;V8;j9plwp*qb+RJEa%gSiDI5L}7;l27Z@YZ4-4mU?5 zN5m?{yyr~4FH*>*;=3i;GD60x|C|l!dWVM-4MXJqiC`L$Z5`AevWt@zWC#JNg!6sv z(O<~SSdtCjB9`7#h1$0GLE-&x`HX!iOtNsLtFq8+sV01Qc(a@oEs&BvG7 z0KYTfOQ1+1#n#KBQ1?69$cZ=&?jGA6rrA243p^%)HcMhKb5woD621sVylSU=s#PRw z2!_*(B)rv^zt05?6}Cs00uE~}p&xvX*?6r19>3@pY_VB0bc-2i=~PF}u@4U5d+yHr zuK4-P8sF~tu73V(`vf<{hWxHh-Gpq@}gYQ~K7T{uWq&6wI9rHch45j2oYt3d2LOd4O5`FXb+`-GtsNr73I;^_mJ7mseDpGebUgU#?`R;hiXE zeiI$dA4@=RT_%+3^m=*x+Fe#v@iMD~%61TgE4ouR#OrpqDZu=kH}o125#anc^(!fa%oW%E0g~% zIN+<-TFZsd%h=91T@680XVKMRmoL*}D2(hwR1ACgzXxM@9jKLZwlmY5Iu5mU`dIY%Xz3X7#02 z{?)3ryWQPk+_4-6ISIV|Zk+a4Di`N8WfP?#BzoD6N&j=a+Im$y5TOE}D=?q^FK@t+ zm=HIJ$f(>bRjHSODG6mtGjz!Q$Svqu%|D|tLD8?tzo$E>8#~@PRXi)=>bdm{>u<`xV zejMm26#wpq8zUO*G_qd+JI7qE4$Q368D(MRV-|XihS`c1Mq%%AN31STYr~Km62W^} zC9^*HoEix-@pbg?Sjm}TADNO$eHK+>7DLSL zUeqlVPB8?b<;t|CtYmD2NU&f*c9CKlK|7G zwl-YXa<|;c!p-ST|JTRMwVq=CtnzZ5!eTz->eqE~#X7hi6&cAhR)}7spuNE_pDc`T zt3FATFaG0BU>%Gu9IvSO_&BkG3WktLESkoNmz$^AcTG_(S1lhjCF17&gsOLRXiG;I zG;_S%T=|GOsEtQ>jPrI3YwU2ns2)Q6ja(^nFbkyah~19p@Ry%*y?nIFhHyQ>Q8or@ ztahXOw^RNGnpqC(rWws^8$@V$@JIdq$%`*T%geEopFy|A?Ml;AL$7%=W}3DG@Yf2I z>jt2IL}JGhiNu4-L9&@ouOsr0Vlp84f+CCgl5bM%y4B_7C*@W>uM3S^aW@D^%ssQ; zGmRM0uL)AjBUtqpa7XC#)Wb*O7$y;5zD~rA?cZK}zlyd(xsDX48kiU1#<1RM2KX zM%E8Ar6J784$N!PYqc+@sSP6Hd|H99%#7DGRIatUhLz^A`>tq7$3v$wHdxIuYA@%C zf6(q}eh!g>OBC4Vh44N!19T=!8LhzU>Z|kGdVf7tGr5r*(}9`Xcfll+#TQkxe_I5B|blq{uZ zq_1_bUaoi3g1zvmwq`#yh|+JuM@f6!yL+u1Cpyo}tzWqWZO8}?o3!G5#y04>C7z+T zub?=7%-2aH8|!%}aa~c%>L~z~X6fGUM0X5lC*-dT#@N?t+1E-9$EwQo6>7Mq31Nby z?EcOjt$L(SMjfPtVan`o9eV|4|MEd&5?b@**ED4@-n@=Jp2^6}Ja=m(;u;Kt{qlq-r9Nspt?e!ZnO)amVpu_MwYAxP zy=a!qg9C{|Msc%ex|m^6N#!QRpiC<`)dP}+Rq!PCZs-m+rWqQ7!{=n@qxLC~h(_Qx z4if~t;ZWD8`}M~u^};@-!TlIJc(90yzpMCb9eK0@q6U;0ko96er4G zxL?nGOlyfqWol4YVYL-6Q5A2xzcSb*_ifBB&*~!i6Pj6FSF(N$7D7*N(ACK$qMw0? zhbwf$!^?H22%k^dCF*r&ha=CUfU7`Mpi0a7Gn&R`1X^QC@fXJ z@ywOjCFHfwj#1uue|w$qi*|Rt#5A;0e8RXjodpT_xGa>?2!S|-#1iVR(Ot7RaSZzh z61jY???lPuxnZS?0oz}fd|0ZOpLdBg=5egtNTsJp9CVAP>5chQvh$i4m+AE@%d~mg zQk{~8A}e@fc}{*E(6cVo=FP667K4BNkj6uAr>3NyXlp_{aM_U6ufBXu?od4#Tdohd z)kosei zzb5xlu00tIV?sIG5q(ErtGJZF`+x0u;XUHY+BM2zg7M-+di;=K*Vz3U2xEdlHX#FEeAP?S ztQHU$L%P=I!U!lM45}6goK8^R!m~ERo4$VS`Q0*uD1YokBwVc-fAxd_LylZE4p#QJ zhz&{vf{Gph)Dyw3ICJGew4cUVI`dcDojyhdEu1m%%eu{az7GykF{L>Vs4#u8qtyr( zF%X`A0)4Zt)>J$(&5Ko9=oOR<>cGW~>MQW0ha|UT!w%v*hSD+G-u>mofrn>wi!xwp z{JZRH@=(-dNdaIe?39=3+2G_A)0Gkg%j-pVzC zp34r-H^br~t)MTF!*h47Y#I8*1h;@9!$e>K4+xlwC=I*X&$o9(;F*qy9itE1# zi?t*FK1avsC{oN6m|?w4#2r^@qDmEbY9U1>XzpR1ni@-*sjF*<2w{YfAbIe{Nvaji z%OHprzMo#S>(>An{n&MKdV1@Hur+k|6~3`&jDrnROgI@M_G@b=#0Z z5`==PrlzVU_8f9d2+xKmr@x-h2Em#YY=Mt2<1pG`&$`Kjypb9{L%CY1rc)-!W zw)>$P)N-hl=Z8H5)%YZNL?OHJy1qMDR&7^O zJa@PY#;;|ozOdfu3OM~l8E-$Vj@(Lv>fD1yvSNH^Y+dlM4war7wh z#(k2QMnk`D*!zVtJe-rs>Bf`uUU({onpB7vR2oum^kp{2V`&I|{Hl*kb`oe4KP-IP zVd`JeN{w;6ukF+=j3^qU@nh93EzNkbzoV;u4~Wq|@BUr$RTj%(jl$N*;lY6xrjhyc z^{ZH8%z}0T!_c1$7<(rUM<))^qjK+5eYMp3Q{5+6vHY3-kjkQOtp}jLIG>E`7}%4W z94GJ>LkBM7giqCkF>t<+q*k-qiSE_!-aUO}e@~EzGxXUfcv)p_D_{2=2^+7zTyM^r zjd{3#_{r-H75IBLjT1STxp$Jo-wmvcUNCO_<`j&9k5%Y(GnB{BpM)o_RwzFlI&O@S zm8UKlMR#8+U+Nd57{=YE-cQb;yRkPkA?%n7WZ!$`w z&S%?S!nOi$J7K>U94UqKlKT{0AoC&p={|unoeV~P+OXIm&P31>JVsZv!|P zUIJ$5G!_s>5n*UAbR9LrV7q~)R!Opi6&*Ma9UAgbW*8f*K#p;EA!&7EQ{~d9m9Zf-CPJYHUMe0a5}Iz~$FptN{$h|P z|EfJ*zhBLv-V%5xYWgTQ_vi(DZEDV-rj1MV(~O0c70JI-JcZ0abi_YTtsC~o4D;*0 z4@V(hu5uJ9W>k(pp{i=I&dKKLpBmL-WiEhee5&VC{J1pmyCA&g3md@ci{!eiu>y%U z37K6-;GDnf$rC8Wzq{W>bj`~-B5-^Q>01kZ%W4$}=UqB*oiJyu=6q#@{wv3Z)QoRz zo)^t}&BmJ7zPJyW>mI8VG;)Rz+R=N80ljIGsTU?2`=)n~J%r8$Glb(_kl1L|!EDH# z+c2Za{hWYXwMqZKGi0|IQi zRqb?}dqEut?3BT1R>Dmh?0DTY%#{8_p-k6-(L`o(INY+FxRkk`YO6Z}F_~E6cND)Z zDBCStwY!(hRo#Wkzku}#%*W{p;C(-AmMGoYB>(mjgS*~WF8{}eO6)iplDk<%YH0+D zdq!gkNUfWDZB75yNNPpm_cr=THLuXq%dJdq@3>eCWb5#S8EKY08iptZCSVl+v_K-? z;5AEG&u3X~)%$kpJnaEjGB~xUU{*mdPj_KrE;O|4i%U*4v{`R9_>NQHXdCmM$OwxY z4t$1xKqvPx@$=jq?)}OYghx>dDzEomGs9=>q+!8~(yn%^(gDm!EI&CJqjC?w6LK0J zRG8hip25ftSSuJ~8@l z+{=rk|2^g4uxm%x-9(2Zo#xoeIr}NW{cIX;dPySnUkhtXYhu(ONNYpA zzY|((uoi|8+|Y;T;S><@Agzg{L!K3Nsl7Mw+(k%bgeCkf5zGNW0`T z0<{->oo_zHqD}A^Dc2!4&ofV*WvbKx1qpd<4(Vd*{lccksreV{i#v5|@InN~XBYXj z^rl~Lo>K>=YpvX6E$gb98`CJGq^6YNo~Y@ynpt_zj^(myL8~gStO9aOc^q|BU_16y ziX-L3qsJRmUXDGajDOz)eXbVxu8LkKfsR%^#6?84DImN+TEz6o>0Bd{sKy%0>t zdvqzM)kbgRY9$aJLACGdG%4F-qmHQ*L?Ja3(m`y-mSCS_z@fV97Ljl3xT5G^-n6+i zdY(T#@B5%c%f9+7CBx<+D;`Zq8NT1^Il0(N7k;0>%2$#U8^cS*rPzh?R6!(6^ z`%WQK;+H?qG*TxzQ8YXtiE3HtOpn(tju&K?(eiT2uF7xsu+oP1 zzK3B}SlIJ^zzkQrSFt@G{OjS`D4gb#-LZ}Yr6mE!iTwV^A2<}*|M21G|IRDt@fXao z`|viZA`kSnznqT96bu!_4vojw`~>^ae?CUtc5r=WxCABrrvHuho^TGXt$41Z|9-$r?VTc?% z0dsfG0;fui-}CU65Q(h)H5XN>&56A}Zdtv2eJ%)hIf7I0L>Ry|yloE|HM+q`u)Y3D zwZaUsxUSz>d-s`Anvze13Jfvg{$Jj~F z!C#=zTZpxNePO}e*7mk-1HiE+oL)f)#T9iV0nF^b%8IU#N0);`>*6sXl5a9FC+%WT zzp#5;)?li8e1_A!!rsxw1@BW>1O?+G$$$%GQ8KG`0JHI1RRjDSMrxLr%KYU^k|?7;F|drC>!Ko zt{ZsgRVvn9QhfrVx#qA*k$82eX$yYy0T`dLozW7n?{B{Np&4ab1(qE3POBqB>=~HpUz@XJG2}dU(e~jf10^)d<;^vf|DsttGe7yKO#yE^GAsfO767R zZD3Crk1$o*)yKm;zh~QE-C0zZPw0*2G00r)izSR;$965*2D3 zs-aCziBH_4;ztacfUvd`%Q-M(XDn@afyEwG=>X&+zOls^Z=ral=|2P4ul+akFA%)C zNGk0bu{SGs@9#hB*wmo*VZtoEhsj4ySrhA}<5u46HFMdsq7{3(O5M1s)3-SNKV+w+ zfN*T~ilPi#c+#7#$91*d5#__V;Rjjwc9UI}27%S3T?Vp#{_|cvDvfU8=XqJ9`^Aq` zdxDLKM+q;_CN5j0XkJ?B-!AxtkHca9(MkW8U-3~P?F6oEhZZkuZJ_rD=(POzH7tUk zE~jINpoKy7Cp&XYaP@`kjr3Ht=BEkXKLZB@!%zG(VT5rBdjFwO`(`@3D!6fok3Use z{{XXld%fb#TAJe+`zPq?{`7FsXIBQTOrNm4Gl0g#z`f(8m7%|RGq`0Q#0(*?FgY^< zO`4$Fr|m}iqL~0tzX(L4np$Oid{1~e=?2`;mL?_Am_ODGCHYJE(`=i4GfE5~GZiF0 z-W`whO2gkz7QS3w4f0%Vr|-o|8BH6hC_$Pf-luS!S^(crBimSd2nCp)KoS-qp{tt! zM&}vpX4ZB>*+|Fe`a#@IvJTS0(nsK-9tEw6=GM`oCNV z05%o68X*ercc7y|hb?Og@S+!dUf>RV5%gvb4j`S;&CHsRl{-0S*Bm_nCTeortWptT z!O^J&sDh?lEUc8gaj<6a4edTAh(;6J;<_Kd{?mC@ZA&A0yf-{`0_H%7+h%lIajX6M zw-Y>>Ug(D9j%LqEd|0Mz=0R?G=7yDZ}P)A<+Id`rK>j++xS zW`uSa=;%dBy!!9KzLu}TT3?h2*|F-u++R=)31@=sq$98o#Hk9!Yn?Va+ks(u8=zoA zNH`srS?rn%P>sd$lBSGr*|V9x#nd;rVmtbsHqHIy6nuUuu*9t#nTUjcVo67R4~1fI z_?dZ=!(#<7cwi1OJKd33kId{@^zS=-*L@BpC6>IHp(K$WRBBN~&uZo{Atd^WgK!Yx zubOx%W?%oABqt=y4_n3G4xOswLHrA#Sj0XBLiLq*pwMz=7~V3p@!mOxD!my)p3>sN zQYpVdp(e2JVCL?xEM7SE4Nc`gb?Vr-GidtcQ)Ja({g4ppRLC%+x&vnhk3GUd*AHSe zDp?`EF5rXx+G#u9PV?RdHc!xetCTlP@QAH!m8g1o(2kHZ^m9~uAiB3PqbTL+XN*F)RAz1zJIf6D>F&t#2_Xht7#d^BArPqONo@GgHn8Ml23r!tqdH-f#z zom9aC`1)8}840XVE)^xeBiCOSzY9&?C(}7o9*F$Wy%)u5Hn{rtH<(6`Fv|I%;WLhEXknI8O3X+Hs0 zI*}AJb*-}Yg+ogs&8rms6XN{Ph)7n5xtr&FM<2zA0ZWSvhm=>T;7u zQJVkqLksVau-j>&so4C)XVan4ASudpS5R^l7Rj7@+Bg#t?|5XnIFSL3d~h%J;J;tV z)+;c0iou!MDw?|E1(<}PYSc=36)X_lJqp!{;MZGD_XqZfn$)j@Y@NCi=>K7O`2I%=03tFwDNHXKp<0JjNJJx z(?~N+R2UYDIM6xgK4pTw65x0)zuo{R+vOKkq6w}l~Km{DS0Jk2%UtXBYZ!8B$R?wey?t8YZ)5k3;s1IvNv4OqRD&P09Spo%jWjD z6_@Q^)}&M&OQRhqGh2-qCZWU2xXB0ppGRvKWir0wy@75r24HJT=;pJ_)AMKf zq_f3|w7DkSC=Or;$(GdHF_Xm@14wGpgRnu|$Du0fwNs94gN_bHaU1C+(mR3^ORQx)YagA4Z1o>^L+Z!~v z=@Ah?U!~EN%RmM1eMz&Tc8UTOO#Fk;ef)WY$+6cN78Mys?5JO%YLy&G(R~A1=0gzc zys_g_anVvbKLdb-RSWJSeK9Ug@OjiSd-$B#?3*$TJ0F*pX0*OPAsV0+INe9QyH*}2 zFE&-N^VY77v`zj-I@M`>>fiq=`vY5ll*~oM!3-|M{XWHJRwRe@N8PJqdwIF+J?iH$ z0w5qYzMilj@RJ#kwC4Gsq!g?vl+iX9;Hk|gvd$Ysgs$OnBc zv=Sl}DJ`0?Q8q8)w`24(R*q066}_1RD5fM>Z-Wt0d$BC)?=(siasqtO0yc9;y4>H- zUxDSPzuNC8)41O~Tr9UFz*K=c|GxmV221%k@w1l>)8vaPZFE~@81O~8ULh{{iX)2E z3?&A%+Z`2^po_!>vaAG%i-*VQgd(ppQiGk`0BfS3`|)2fS_8-p%lKH!#!W37H*twm zJYMh3+qc)6OtDH(k|YNQ`ulo&>4YHwQnBb!W4KHm6^TU2e8Edpf>9Z$6^a5W5_bou z_-#$fQRFFu7J%H)%bSeK4fH38(qs)P5V+od?as~5YwH_YHg00QGtuMq4&Jy?R$A(H zxduNQ7#!%wms%u1uZ(UqE(aqbkw_(%7z*VHd?A;LnWk5hy-(D1439r7*cFPwh}TAb z_Ha5E$;eX%12_X_ckq6>YO7XSP4kpyQ_;V@+xf!JKgGDA04pPThDXf98m+FjzP`4h zfsxH&vrf-UPlG?{p9LTli<(O!RoVwrd=vc67<5XeQ3+%+Flq)DCMwA;W!U|&q5OLuO54*Fm927^|s1G*!A zgr9rK4JQ5BtkVJX`T{zrD~vQ2M`A4_daVoFK@+LaRALy!EVU5pGZSom|UKuqNNA!wl>=A`bQd*Q~Uc`fGdKJ1waTmIR3w50g zx2}exl-+mR84zMOkU)^93{D6~DH}OB@4stQK3XJ8y-~5cLVe;Fk6j(Kzx+l&&0UTB zqD&pFEBqQ+hzkmeG}4p`f@yjcx~~M??T%dRp0TJT9HpFryLsCpCGwQP1AvZo`tO#h zTGd2Z%Hy}U8hhT~-+gZ4ty4ppAr7fnRHcp76-HxW2!KK+G3ex=c?1vcQAtIytfCka z#0eoPS)|5h$-z8X&_SLucmr63r6$S@$_;dg<3Ly4fv&pla}(X?Caw;q=nZ3yGIg{} z6^&&>Vjv_1daayh(v)d>72b-5UOs@jP6ncqMQY6MyOsAi=_5}WJi{BB^}1)(M44W( zj!rHX5XaPv_rqRm_qmCbxmY@oibbXBXo(_Ps*WU2&k`3D=+x38CV>V>uaZ=xZ`4Ny zqbg~^&PF9>Trj*94Ut~WR#cKF3wFp;Mq02;9G+RJSWVyKICRi-=%DGt-su-!{*=Wl z>SR%^eECnkGOCkBp~nES(5VQF%?X88ML0a+*Z$2BtF!3)!gu5wdK7CwThX>OK&FRf zJ}Sw3795eMj5Gpx9CqKW62-bgSp%JPEG7kODozY8l!QnrjV}L5z&RoY86noGq_GBe zrqF9-zx@wad|lS0GuSukdvZOzGKGFC8Y(K$X{EeZa0MgYdH-D(HI^p}F33|x+Obk@ zJZSgb)=I05%17}9U?@{VNr)PgC?h4r1qCXFM5mI<2=@JlD!C*OiuR2rY5_6`=PBse zzSagU^k8IE!s`GoZ)nyP7+>{MIWvPiWn>89D78q9EmC86n`3AM?q%qeDRe|U2uXoT zPAFs&rY#{*=v2~+!;oGTl@uP`m}j9gbs#DO7nSfa<})0n+`*~5VZkr*l#yw~Y!0n- zO^IS%yy#f+1X1=U%ASZpA(O}mv5XKaWD+__Q~D^@$Sw{gY5|o@jN190tTIfMN@&q1 zE?2@$W%$DjPXAqZa4H{z@QyrXWCy{B*BLN717ndvZN|!J@+xPA>Y~zqJHzKtVkd7 zl#yjDi;k6E2CcNZrym(d)RknXHA|sfsz|7!ES;6HGFOZ?x#lZN( zHriVt$Ww+;FgIH;Hw&kX5>*N*0+hs9{*|h;Lm7*HQL>l0vk@sVpy^epkwGUa2}h|FL9xsfc|jo@ e{J#JI0RR7jWiUGVP|9!s0000s`uWhTHRgMU3K=VbE@~=>#TqC|CRtD02Cx7WF$lsWMt&`?@>_Eu+h;zd_W`k zjD>+sLP$nRLP$*fg^Gpt3k4G;F)YRf=uCr%^sMLi$W=0+k>Mvbxy@$ z>KybQ6&DYmfRLJomX4l*lZ%^&myciKo1~PqjI5lxhNhObj;@}W`40O`NbO*aK0p#S?OCd)`xWsGZ}OI!~eEQgLojU;GbB|HbJ49igEA zUyS}Yq5sY2-y#4F0q$+V5HJBEfU8BiymkOx9_arDdJ-7#Xl*w!STEKy(e?e8kv-nh z?;4+%*S5pm?#$WDzQn7>mPi4ZrO+W351K zVUMxN#A?dL{e$e5;cYyt#{QAfMP(4C+d25@V?e)eVr<+iQkg_qj{{u_jn$nKr@6D=k-LqR8xfb*Qw0y> z$Nbg0z4{qbutGlPl)lsi<9BzGiRs)RqA_i1{o_e@v%9!^&2mEmTodNyu#LG>q^G=U z!3(jwf^Ve1cOzk4J@|Pa3>je1Xek27MKjgxI07-6kCsLo)M`Fbo=lA)8e9pD33%dr zB^(&88xP>m_w9!}Q&lX{mr^oEp4aA_9%kwvrsTWhoVkmWlTaF*IdX(|r{saL9<|=<4JnOb6J`@gM)*Mf?ZoDn)APzk=U-IULT%MjWfJl8i@V66z^;I&`nQj{iCb z+O_Jw&S7yIIegAV-`9YuFD$K~DH7J+2>s;Wfmxe6nzlF{HPM2uwSA!zDW>4!?@Q*M2GUwr)?8l3t7`N zzHBb*bBH-+yMN<-K7>X;sL$W1d2%jp`-*JNI12ZaCxgz3nZiR;56%oNHEF7y^=eKV zTni(e-{;-~-xGQk7T2s3{s3UBO8ysAx~4f#RO~t%V(oiCmwzN+El>Xd;Ys@S!})7< zR|#m(rME)|5B^+hQ;Gs`n^$9gMavI*$G!M>)6WBHuMOaTWekgM|}n~ z+6uc2{ci9N&|s6ONo3JcN?136jUwNoszIh3Uq)^-mTwh9ZcS*dL^TN;w z=mpW`Xrs~hKuHRaRLJ4dCw5g;u&D6@;)Xdyw2dUHAg@CJ`B z8@kwGfh3Xx9sHqH>?p5zB$D>`X8m>gA=7T|6snhfj^4c2w6GR^fd^*q%;5ul7YJ^? zN#7@#5!S<^Dt3}2Aq(wblFJ*X?PNfBpy+cm1W&`O&Vas!gpKi>ZUoFOph!LM8``H)fj_N7U1wocbSKnlv**<H_pyPhvIZ2q{@}DXf?TZt zGh3!p0kvmOq9)=StHeuVV8(UrHQFsL^jMP){UUaA=Hp~g()+a#Lz4M?&~6opA?^)@ zNZI|iDOz{w9coa`7>t1-mj9=3&Ns$ZGtW4Z{ZU914=L zm^EfpPKVYHUp_H{y;Fp(w=;rH;*kJ2@15|61*A)h;Q>s2yp??$MfK;~kFcsRc2RkG z|5N?@xanVNCZz$f)gu`*2h5Wch|dRo85h&(dhxI$92# zE^|S^m}F>*3#;!jEgA+8JgVZ+xkCP69Bo-BU%r6mm&bP88)&QBiG>*Z`uFvgR7xb$ zC)m&;+3#cN_f*X64nAXXe$W=D?#fmoR${<~w(ICdflb)TeNzX4nkVW_f$nELgJVsQ zb20K_!*R9F1#9mk%rx$oxkW+94goNFJdi~0IRxj}y7TDs^g*t#vvy0RC$(-ody^zU zR&l!q|Cy0e>q06iuiUR_M^AMcXD9A0Z}@F?y7aT-+hQH3^k)dmQ2AL+;!Mc4%w9jy z=ZEcH;urqf&|HQG9^4)nF}vhTT3d2nDN{8A%-L?Lwa%{-M{{&I$J!*|6P5kx6xkZh zl-_i9~P;xL>FC2oX8$=u?`vYZZ zWRQ7Ug+4WhW|Si{dY>jo;wyQef<@S#6uc2 z29PK+K|k3dMsjI*f&&e@P`|7tkZJL`>@%FqPAoL=Qj&Qqv_8w06S{#H7m@kcheru_ zqP+_A-I@A6>x)uGimE=&G!t?R(hCVU&QAB^aLFgxSze;a>;eA)Vocd^!%GJMRbN&3O+Tz@jYZ>5PdHw<5wESs-Kdom^IOmmzZPS0BO9xe1=YxA zXyx1(Yb`9W)>`Dw#7V9&F^h&vfIfjY{i*)W@jNPqZG|!m#7%1F?Y)~z@=UopS>^d- zywMaxVZ8TzgzA6QI;HA7I8?y4`-zo-sEhJftgwWJL$zS09QHE6NUwU?_k2j&O=P4w z;qNV<@YaE}e*+=?=U$K*ulg{2wrEhiqswXv2q4Zw46ZlfZSIgV6;BE)yH??9ol$hM zb0Ek_US45?wLY~MxA{%nNsFmu)bvnIn+By%^5FE~Ko>`vQ}`$;@l6bB3Ci7hipHe` z8|#(w3<$ucMuYRMFmlQMGaGAnZoA6n4@}uaoQl01O==1>rLX1|nf@B@H&|PeiToy`h=2YpU+I;>zf1)l$V-}A+Yo@aLv)VM zC_|o)pbhhH^Xc`)wSKPNXB=%r85_?nS}Yk(baXmqoD)S5bmZ5n)sj*tl6<#wAt%i_ zMCc8zMFU5d4&gBP24n*P(Y#o}i-l><=-MW+z+RqoeB(`Qxc3F!H>J^1ncF_tM z*xEXX*s7xc3AlYa!BS&A^~HE%OxeKbi^|#OPsGQOUhqwqa$ESM$#Dhbcpfav@$R5G zS`Y}>P3fd+IJ~VZPj`qH;0ILW(0v@dt=GvX<7mOrhHr|opTTWQ63}?gi7kfZu3C1q zrrp`)JfSW%NjR7%AU>7G4c0I{G)=TtFziQ#ZTH6)!*^nB7)8*4w+w!L#!fTY$~~3z znlazd_1IZ_qt>RB?Py#!(L)%Law7{L|i!1#kM7hK` zkEF9#ncY5&qb1#6v0d2B{^&iLpYt9W3)(a#N^f?Gk0B6{t_J{4t#Ymzv9OBo^>Zal zf$YE;->HSJ`N=z%HR0aQNc=?4%@&kr-ZqlZj#tu75V|-gyiRn!?cROhyDj0HNo!J? z#tyfJj(-4&KajC^*-!NQKt@_2P|+{NWAlu=YV?%#=7HKAopyg#wYwPkv963R97S9iyUVsol6@t zvbH$nm$C{s`65Bt=6O_PmmFkhfRJq2^rZhFG(WTH27M2Bu^yIJbj$xoK?OWNGK)KgDp$P*uX44(yJ_XAm=>^2TRr& zbndjK%R&B~aaVNape{Qh%C0C^121gRbDe`hoCjj8fq%=8{|N+6Hwq9PJRNiBpERet zmAI%?K*<(xJk&+ zjMtOaYRQYHYOdtW&X{OZ{U^xfW>hKdvbT0N=k|kAi+r*{d6nntA^~D$dyD&nXbg|c z+G)vaOBILaRO4?!-6G>m!cDTqk%Ymo#tz`;ESbTnSDXX)Mben__C9vcIL&Bdn~%B8 zveBsy>&l`WMw%7(^+p$!D;eO93A=m)18m9YjZblhaFrX%2?XQCe6Vy9=h-WdjT7z@ zX=>)L60&h78DP-jTpuZY+LE5EM=?<4l020>-vLs+XJlM*uo#w9C0{IK{`5@^Ta6=S z4-i+as%2l{D{q=$WH`Sn*|5W6#EuVlHg}aPMs2Pvpl~a1Xr_ApSU^e{=htGFaEM7V z7>nbDlEy=WRo_^d)hrMTLkf9Laanq>Q)Kf~x=#n^3(hby7xAZWWMeZ9 zgfIi=Pv`!5l|b&Q=zC%os|kgGT~ z#@xC&TQ@rCg(B@6DPD?(I*Q|~l4rin_eAiscrSZ6rXt8kb^idBiK|@uO3&GEH4%N^ zcbBX*PSQWH_^J^-^z{9FB*aqx#ZKN2;QHhflYB~`-EYqp5F z&5Z@@fyN2gi4n3*^l{k)ty_XqZcaoAzc6)RPAEW`xN8v_6@qO(`*EnSJxsi*8gkh6 zp$L_HTUHZ)d2e#yY2YrFp%w3K!IgvS(!jPq9V$?`%?4FT_y2?bfm{f{jz*f6MZo6M znQX5?<)7hPVvPH=;)O{cJD^1U>mx=Z^Gb-$)OD-dQtxyrp|9dnAUR1_@|4Y0_pP*C z?BvR_3~T(i)-Ue7C!jxq308U(4=6IC6p{RAX5C~4b1oak@5OR-gjVK113kV7UN#FT z{~(>^IxJI#wmG^a$I+Y{g_rMlG0ZG!)F-Y`eXLEzpTIc~MxXiF_)2s5I5yG{e{dMD ze@cKl;6-`!eE1cA$aL11gQ1GUuO{1+vG!c3v?*1O=?~{zAf(io+39h&MdMeYi+6bn zx1ht8RI^9reUTkI@k^4NYCH0M8oZJSu{O`f3b;C;ag3>khg-nm1fm5X78ZdQVK@?$ zC@#5A-qe>*i;&OY-@E@6y{#=$w7(c0=H}3BJz2PI!5x!lF{l~%j%?z(YCv{`N1CxD zCEV}aK|H+wLUGd$NY&OBm;zfKYVFn}W4jST-Y}YSGI8+0OLjtYhOCf?;cWi{AT+`i zTcvtaKR)0^Ia+`yyj;JS#~Ha8b=8%BeE(ejo+jCKlb+_$ac}v(AruS~7vjj->d4bh)rXXFH!gx%pTHZ?eqt=KE@tiMnMJDo{toZKH(|ni>9S-H8Ri6W|AsN>E4HGJ=OY16>>AKVw20?zQgvl1Stx(T<0% z05|ySbH9-jSJlybvE8V3^@C7u%dEymC6+qAx{*b6k#_zH;V4kF?_2(eaam2I$rc_N zH%4UlsQvT2>Rz&RRfhv^FDF6lRGMrQXUL|hccS0>7r6|)spxG*e&JNrd8;^xu4pP= zjr3PTS&pP8wsW7vXv zR9$jn#zftT_QGn#)AyZ}H|#8WWE;A4Q>z9KS7(!{V{3|C7bTD;9!LF&uB#O^ECdtA zgv??-Dv#aIa0t#Q&o!>_8#Bo3M{XboGJNj#v#FZtkoZwzr#MIur?X8YQ@OvQIY9y} zoXx;$GNN+I2yTw|Z-C>3r}dQ?kS?h#aed+Cgpuj$){5OG&Y}2nPi)+YgDzMMxQ`08ZqDZBY{~7bs4ya}XUV z5lH;3V}xafhKg%H=TKH^Cw#Pmm!Ct zn?m1?jQxOy_-g)&vrkGstF1V_n-(-Ktf}H%%S$%iA_AZJ4}jUo?!{=@@>WHMy86?r zx|JPpOP>n$B!pK@%DmVN4UDb{F<=@L^Hp2ljanD3t*vm@$B0wz1Yb&F^h8 zpid2AKz}9~c*Opy4$TssXB|pJxaNYEu?5kG^8vQ~7!#T*rd+i3(nLOA)6>WZDi(`V zWsRY(NagP)QZD=P&taK(Amv)si}y^0Q?>|)uXZXcz)mTlq@(KZcUna(lch(xZ%vLC z>lz(G`L%Lg@4!F)wi!Z0>b+>4*@Q;2L>O-9v{k3F-1M01Bb)j;q?xE7RF=-{emf$1 zxtrM$-W}W!rKZm0)1BUc;^Ya0V($avby&L-%~CctV({y4>9ALchdJeqxKMA5a2Ef0 z&1wgcz0JK{$fPTd8*t!vZ@NP9dN!I!m@oP6>hojfEme!V;Px$Tr@^ALv`CEgp~vR# z)^K!bEM;(T2Dl*M8PYPLcgZLZmaY`%j>MA-+FT@RF>lV|@+=@SAl+>64IC4nTnCTw zki>vn*Zo<}3)jMK@RE^#7t5@*n>>>S%t@Z7d8z#mLkRnk^i2?QWhfo|yO+sBU})=+ps(yi9)|RR zdwN7!VGDH8@~mlRRyDeD^0$dYpvT8K$18EDKWO2ofi&Z~+IY6weA<_&@-QXm{bqA7 z*=f>hm)%@L*o+bEM5m@Tg3tcxG5eyjMBTSC=k+4logG={dr@3=WCSP`Sm?^|JluJeK^h=~jJc(kXDu1Q~RoK1cWY# z)MmDrxBHyU7M5(1o?}Hgw4Nob@$Z}SQ4&;eq!`Ko_J#oz!cjnB`Mdt z-Edvvs&6L9Qo=)MJ(K?>S&6AsxEU-$^WiO^a%~_HPSVB;o9h?@U7G)W%<0N7SGgWD z+ER->XKsxb=OW!FOECCr1`ZcGlX4+y0;x|Htx6a6m=pNqg_g3(nNoEL8Z;eZq9Yk+U1E(|fK9-NLeJglwgLTuA zp%co)V$fsvK+8v;HzZ*&2lvMQ8ZPEdqWS)x^2~od)2YW>Bfs;` zLe%JJ{mI45jNJ*%phGTHJnm-M0dGpy)oOVy1vi&e?TJo)nX+RQ_DStYlz0x+J|7Pz zO|aYji(oV);w?MA2HfXeWIHnC+_2OAY^uhCAXEwgDcn_JCf`t;hh&@I=YEMl(XSK% zlKy?$e>;Z85eXX?!ZB>>JHM&ae9%fordt$E={IrPGK-&m=SS+%NXz)+Mmp{JY@a0x z^jCW#DIDwiSHsCBDm~|i7PW;4vG!d^1=LnQKqCkkF>U=g40*zf@%-^-XvfdkVcfKb zd9}WxQ69y{)()4WTV7+)Au<|3i5l=g=(dP;LT z0+}t!LY1&B?U_J*+1Dxjr&1Bs6YzpLEpG`-7#WATK|kb2YrL=GrZ|eB@SI2KudN4- zkKpl&P&cA88eBfsrD)4TMZ1XZS4_16pf{?$UDW&l&_Z8N+Kv!HXs3A)sQV9ap0LnU zHCiNBiQ9{<@DJcx3pjaPpOZ1UuKL4Y;awQpw9YA!Y?cG6uc_Y~|t ze>BVU*$I|TrSZb5@Mzb*EM=B9$dfA=45~95cTt<1VW)~B*aBCLh*d_KBF3nJvD&%5 zeq-lz{RcS7{$NA+T}1HwQ+}7zD{nOwpNUZ1sVU=|f-mv?#f$j@Z&wiQK_uZt8C z#;VjoN zEH|#@tyFkyUh1MlD6X_3*$CjtdzTBsryi4r6Q${0L#}jp_{=HN`w3v9Qw4S8+V$&>fMb|=D}M7{f4+32-(iqWCwalR?e%>5^?IDX<~M^@FEtz;A*EL zp!OPp1DEazselaJw}dtxeEh2U(#wlPl)Eaqy8YNg);l*|5m1x7NA6-o-dB&?_?l4S zTA}i>pBn@hEYm-0?d1ZK8eNPUv9UbE2Q3a_T~|2BMV8WYpUeL=2XT^p>45+#g=NC) z+l4J+&#h~{7%d&Y8az+6eUfyz|0$j*&7V@1eL(O6wY*34rtSX+_?SM1^<+AQ^VL@A zWfWTMy<1`VWEhQy%A3f#d^5Z~C&@?8{Lxyn*mPuzY)e)WM@qcp-DUvK_mYW9eqrG= zn%|^i5G5->&p4Z?;LPwK@{v}B?ZP(3m);xr0OonA$-a?zohz*gJ+>h0k$mB6z@jGc zb#aAPQlZ=uW-H}el|`v3(1P7e31?;fM7On?>uyO&%L%afO&Jm2x=%k4t~b)vW{{|l znZu-9b7+M?+5fnC0QRkKx3GNot<%{iW~zhlb_veS6C<4w_o0PKeUEvw^XG($RHnlv z+CKo^&pFUxlcT`8X&brhuz`{+aVEB^9@>AHRlZ}ZYM!ycrkQTy&&&9eRQ*JMoNP3r zmPAhv_X0S^+=Ow?4{F4I`nOmA*pVky!939PWzJzkP>15VPW-i6!PeGxazVo^jSroW zTg?kmvPjM-!m};pu|yg= zgR>KW4A^F3&9o!^27c8#Z;_chGM7oVDS%&%gHe{il|f@Y*4h`R>Q5M#@-eg6@Jy9X zI^TQz=qz_|(wK0vzDj*F)OPVh#GPgGcSnueFEE?~h6JuqB`t5P`bg7B6zmb0!OHiHgVO?VgXP!3gDTxnpf zA|+?q-(eHVB8Je8=11l&#UGK(WWViX2bJ%BZ3Q2DR?dlKX!4Qo;pZ_!Oyt1edd~IE z8Mk@SmN2}3fFhT&r0m?v4>khwTokML6zYpqAD+wO+v;OA7l#OxRdv-poqNUwQ&e9^ z6S84#xa8EOAvKBn9*?or#n$n^9lm}E`B)?ifb1EZ{E0G!k*Cdz@k_P?l^Ftvy-SWj zec^rHwk%ams;S6fCQ15iOQE6wz{lQS!at4$?QO;5rubYhkyzRMIG5TUOM zTRi+wa8Rs7WG9IT(FlZ6$&7pU}(#hD{%5S^!_AmU1mVkIp|*1b!1LShnDMrQ=* zJ^?}MjIW1Y8=FOuy`2*)yT@4FIIn5J0I7t(A!H+Alw1ro6O^3zTh<&6rH_;EIH&!A zb+-?ET4S0mEB5U}2jWoF=6c&+j1KQ7)OBBzvQZZ*Z|2zD%yAmZ9Ajlz79XCV8kITC#OMhBRIGIru{nvqb>rt#upDl^Te?HExj)p{|400FYXjqbk z8qyiAB<@Ux9Ucw2NiHSgM_+H&$8>ja-_aqA{6?bi2FaX&FQH1YdK)_b02P9!)$@8p zR#@Jp@t-|V50<{y>D5`0%glL0c2fBm_kpKkpq!*+^)od*B4k(+N4@DFYe9mdSrXVJ zi}kJ15dPJAFb~#4rfUd`2I&=k-yzgs$D#ZZoBZ2jqm$v`gFLWoo4C&Lr`+rq`M$Lr zgC5&qlrYBJ&iVC}Ra-&8K^mitD+Ed8o695Wb^rGflrNQ4$^g3d>2;NE)H`bSKoOo!IWEepkH zjnA#)7=@p;;PvS83d~T3O9~8TLDs~sIbThKr4{KxE&DvY|?c#K|-xzi3d& zQ)0LeB5x=!>{}F#p-{1gE_HPTnM3fkrCr2{v zErZuPj4$4;N^&P{Jh1Q4bHP|k58+O2{^Rhg|{6f+?Wz>emZQ{eISF z;{MJ))6a&wIF>+zBh+&L{gKSa;1ikf6u_evZN#&*Wzl@QGDRfnb7cFj*%D}%YXZN| zj6SG8@^pgit0b4Q!uiU0KK<;?0l^*_ySO*p(m%kgwi5afN&J|Ia<)q6>jG5zj3~`? zsW*1TCSRuGR#P=jjUJcA3rEHMh0$naR!Ru@O^F|5ps_m?VltP(0!DkQdA;?-PJb9$ zsg@k!);0XSZpzwms=VB=RSk-AC9zfDB)^&|F5{)}A|(2iw87QM#phb`YHrWC#?TmJ zt$Iyc2;eJ=oDha9HKz8r^>&wyT9dJ}l1O^<>ke33-`ePeh)Ki!oX{(g_#MAv`n6#} zhe4lyu_RZV;ksluUS4R1Gx{C{Lvy9%#-~bwS*n}F8&W@s`IYVMRE3_(!T|sYej{xH04Ps{1iiP zn>S8`|q|H$}F~LN4|+|oBUJjDq+1;B3o1o zoIgXeY}aG!K-I{_;9rhFc4CGx13#Fe*Nx$#Jt^!%kNAy=XZrH^G|b=&XuRMGPj zR8Y1M2;=!`-C1caU@1AohrcZ8VT314alypn9U{!o6*9n+61c7wb9A{^yk(FEO1Y0Q zQ5-e%zw5zkBRPOR)ABEU_K-EBef;hB62l>X@lrAO53t}p)_wp^7ossDL)>+i^l)+ni9}RI)ZAWk4>YQd}T`KsNOk)UtN-bO6xnE=l3E@Lar10-U;Fg^F z0w#Yg2zu}=y%~jpzBD+)n&?Gj%S!%`+3ttjX?f5_y<6@_+PwMRj3wNy6U1#6yqtA1 z_T4%Q0m~ppxj&V;bgkKvis1#(YQxWl^>6*IoE9bL_m zM!e@(p=dMkNE(H7)DB%)pcII_-E7@CXG#2ooT}oK@qDKweN{){a9?DPbg1_m5x1Uam3$W{m?;!#O%7lF2QUYp_CE1@Q<eGQgY5mOhGKXMs5@qa9)FX<(?Z7Zr)Eh3N4<^a(WO6eYp@Tl! z;zjwj%*o^dUr>>`d^hpMV>=J&0u1<$787-O5HwbXTL$e0lfZU3+Jwn*d~YU&=y|%l z(4APTt^h#b6=_yive@_5xwFthP;IEpRRIa$OgTj$Q|lk#iF-iIa`2WmfN}ELju4&n zub6#DVCv5^(rYOeTZI&e(%V{VEiS<4AkZT03KvyeC5$1=!2(AEj|`o(wAg&&CyEJ- z$Fwi!V=8`jD#c3_>u@IWzJF()@r2rP(&%WDc462jm!gHL{HSqA_A==VG(Qdt^You; z6iA)>I=AbrwSw|gdSoc}4FG`P=+Gu%tLF9t+eLBc%>sw>*beci#-+w*F-KlqFS^kb z*_ONx26Vq1kLPnyNo)%@ViKdmec9v11~?OejT-Vq`*z7<-l4Z*1Ac`E4lutJa0XVz zr3Noa@-5l-$tbFa%5vA)DAwhL_ojpJE$-0*7t2>h)^7H0L@zuFB=+`re6NSkkO%F0 z3I?f&j&~}JJ6o2OvCo3uu?%cMHjx+18UCd0Q3JT-dC7)q2kN1T>|Rvfo9(8&Ral!e z<+e^nHxWOWxl6c16=icZb>26ub;#rqZfu7*K35}t=x;a zXxq56-1<&~8{=QI^RM)>_G=d$lU1h1XM-N7sZtnPpgl0ZMB#l!lgI|6)5)!C(LaFc zePq$-ecjo90$s`VM8qpDlm>Iy|F*(MnRE@-E?{QnUe1I?FdHTzCAM{5vBGa_d z7bDecexAbJVl+%q0!xn6P>ztqadC~OqNV*1@H%F==z)*l232|4N9@Eja{R0vTz&}0 z0TNlA%rWo@$rc+bZ+Gitc>Byz`cxaN02zx8E*kFIc{0cn$q#q4IkPtFq^$#+OU7-8 z`oWz1<1s=NLj;C0<9u%i4xt9qC#M^=%1z^S6LD!dy}>8i7?jvaH7B`ONlVK*1`}o; zn6Xy+2qJ@>Y3j;yC&F~r6Xv&%W#r~DAjQ~RqTFY6XHsLt`niPIIH?6p3Xg z)wYed=mJ77;^d_Ekm6&l%4*3au{CN0cR}>pNzpC_sr>KMWDhcCKMe1rY}hhE8!j`P z7PI|aC+qZk3-?k(H4ho9&nLpAQZZZGG;Nwml&SqfF_qM6*dbvJbl3V0Y4mOJ7SbX^ z+F}HI4rVF=0{$9hjyH4o1wZ~WR?ShQP$P*crPq?hQ27$ikVi7w1GjJHzHY{_VZT7# z_h4BrInCZ)R(Nd*ZRS0jyyn?5uz{eeA0k$lkdj zZS$8Sn`AdVhJ?I~H(|Ez(Sr|W9;){&^NwJBpZ&-y7Y+_~WUY~PEO`hZ6tK||N z8ufAiecpj#44jFbrdH$LgMz^*q5`7brBu9j`DCHqvC@P;L~6t#MIwZe*BgmA_tzBF zHA^75lv80dq`khB=64S%lU>q305Io$4(n-4r9WLW%dTv4qOWdq0rVkAhj67%F~MmQ zbr*B7oIILdIkS~>_dkdXUMc?ps`c@VI9l(cn_h|P>RW28Kc0xCy+Fx&i@Urk%C{U$ zKCF(o7f8^wi-dze&s%>eQ^fu1@DJdB+?T9A^^?+ow_MW7RW*)-f60f@M_;DWEcBf! z3l8@-oGv&!)YVQlByk=>+*dFe$2_+`8myl#dY}+*hO=`eG_|^3X_k=X=hIWhf(Qi{ zg=GvSxd?t(4u00D8vn3=+OY4ClP1(LM5T3OthfCvvFT86B%Px~x2Xn#qa`<|YYL?^=rY%p}azoas1mGOf4*2t0pq^ueUd_)`m{xuBpQJn zrV*ye?!rr6@7}JDESf-^BR|E7Lw+KpP?7S zD)ClG*QJDP`0No%a-3U{;;&0<;CM?;i6!iqVx~UTLTU=VC}U|n9CN+5w{Q@*@ z^_$QC`heW5D?*PYvuKzHhb{VhD@oS#0h?c`iF!IWQJe60DUa)mT}9q{x_a#_OspvugH zSkA#>yVmc|P%~+YJcOThgm5oyX0(FJwQ9MscXAH+kZD#mw-u` zKzJ?!?`$)v@yR6`bbf)umo8l{MO@oXs z7r`vZSHyKPX_lSH3-uj`r_Fh@zOqtrKti z0wJ9SgQfxlPFE*yi%@y)4h@U@&)BldXWbF8`Xcov!SwrTxI zUR{C*-LlX2HJ6XCRd@}2ZjJ;CK6QKTaZv~3rrv`;)s#IlQNk8YXWc{e6v`%fvm0eR z*%r#8RIF3qjyK(|o;Y>%EF;=8T%KdBFbXgd}E`d;tmFxzA zS&R`xqb0QFBSawe0ftpQ%*ft~_4O0#)@p%lL5ySNJz?Lk`zXatAI^@rS8s`)7i-w- zmj;)*by=IQcNS`mzzTC(+}K1R(a^r)P5OTThse~7N()IQ7n=QTZ4yuoMV1sEmxm#W zb+L2j%6TJUyxjvDt^fc_4 z|J*dw$m+ew$r6ywlX1XN+mP8V;XBe*?=_?+)Tp-BnVJ6M_T#J@$FlNMf4|4NN2%5) z@0Kxd`ELpRD?_E&+gI{Kc14+=KD2BJ&Z1Z?zSrWqvqJgK!HU&QnM zU#-1oP*dUe?;Auxx=0a1uTli06FMTHcL)%A5eX&IJ5m&c&_PRZWycyv+iD{yXlD{gn* zR~Fwze{m-o!SIcbb$YM8@`*=jOG^s3Xq7YfIh|c$Hf7I|jrMxJ*IB32u4kIW0{CW+ z@U}^10q^;#(4X)BRU>(y5m;UqvSw{|1wKG5RPo{#6Ykm?|H6;+3B-aV++X^dG9zaY zi_hQ8;yQntlxP82-3rC0D=&Qxj2L`yC{@?gB632u;D!a-jL@66`>K+)5Bp44!Nipc zdv~_K9pH8BQ@NOrEjC&)KMKoyE09ma!ez5)dyr~lB!Qb~c$VfYgT>F6(HSk8`puoe zCc&X;FGq8|&*$CxMNSuVwI)k5Muqs%n5nud^9@|uSbR#? zbttpdu@-Wp+H=_m9OcV69d zqHo4cM_dO5yb|Fh21$BwYA}djV_6jVBXOe9%$L)`3)uxQ(M%@|G?Vx58Hg$0UpNJ4 zzv<6`Y>iwiLM#-(&8cD7{-?U`_y?tr@k`f(QFYho3(iP7KeF%pPhPZTM3{e-N1ohm z%r%FJpqUwYyn{|rbxgJjhZRH_1cP8{&Bmkj@6#I8j;5qfiDb~Qp=Alf@l(9g(nj8w zoV`{HmKGH8GJMwRn$nVx(y0#x#72=2SC)Pqh4mad!1yCdH>UhIBWN2b8CciiBLx$S zoKESeLGmUa-sZ7&>iEuwRTc4%xTG}&LC&kizuDQ<1}fYLn&(mX8cZugj4X?`6$=`t zQC?V|930I76rJUw=rBdh_1z5aX+qGaP?P?9CfD`y09U<`@L)^Oe_sRrQQ7#HFhvli zEQpE6o`ft)eZv)WP}CNk8JMP~kmIAz<(-VuiO(S0v*3k>Q5yaEN*^w9ZYDkt+P=Rc zWEdD~SOE?l3aqmuWLlSBYYzhTkKM^Dl(4{ZC1GAqpt6zbRK&3;F^ATNP~8OD4E(61 zmUMG_tn5c^Mi$v9L7RU7?fU5lsF_;thoWh+5c1EI8Vm#FHY4uc#f3R;=4-a|)1wCa zL!MY#>ezKPjcLznQ6p8sKJRx7yXN8}YZQF+ZJ#XT{r0%SUSoI**Ax^F-oAdB#ee&V z0o@OI!_%9ufG%c=11lUs)-#;kOPnAA@js&B2Jn!qt8Eqrn{OEWU zP5)HYQxr|6B3vZ8{3&IMO*M-GU+7M>9k5UOkMIU=7?yW=%@0FkvYc>uA>D&zQ9N2n zBJkj}M(U(jp}K=X)Z@bIwAXhGD6h|4&1f4#+=7-io)Yd*61TSC(yS02P7NOuU!i*% zT3b;qDda3VTr0;st3pG<^^k85*J{a_b|{fXPoB6k*|w8H<^?=8Oob}=J-q)p0ILW4 z^`}}!Z%zs5(>(0@TwRSfaD;CwBjOpKRn;iWrT7QSv5SPES{HoTN3ZmkHeO)X#Y*Pa zxlZiNTUslLG1tO=ey`aEjVa5`76cYt??Hb|&3u_S(A)@spXF=LxtN&Fsp}-pOSfge zKK6g2d0O)=3ji)6Cm1&}6PI>5b;Z+IDD5Alcv1*YrH{UDjO!*ptzm12doRuqSh0F7 zXO@Z9h|UL9Cevno^0%Q_n5wy z;Qf8GbHp6E#B0FdO+|#F$k$xQ@SAW&38wyZ9qwyLp~{H7oc0DEfi>?!K6eot8V;&3 zd9|e^fbE+Xr&I3GUYc$A-m$zA0PbKXD%i;h6@pQuWutIP?UVf00t9L!{FD&b(e3hZ_C~&9OlGUKY~# zGo-3QBO8Asl^nmp>-tmv7Q(F&`Tm?svbYjA%(NdQA%p@gD zKtcT*GHhKUtJEh;JeXx1i1d0c~dg!7NBw+tG@lLjJyaH4Xv(M;|~Re!jYM$0?z83Lb`L}slE zx!pb#p-WWl-v4W;^H!`)5IQ63H2HPRo}kb9#8aL_oG{Zo0}q)-VFoP3v3zl{I{nVM{z z?CM~HO_*ZV$BjgZ%Y?f0rU&S3q`?M*-FJauL>ccKQ>GhReWgPdgx!L(pt2X1-O@ z+?uq;lg7K4AV#76Xjs>Jpnjw@!SIisz;j0KfO4_?CB6rSnv)SQK%+tMgj$5&DNR3Z zd3Mj6F&*zPeuAtuU9&4Lji6~F{|lO*;on*;$&6{8gEV2AJb8t|4Rto*9)Gj@65DXI z?BTx1oMau}1FMr6$wzc_OL+1n>!!!|=&yV%PC zr7nng^@o;q`tMoD)2T(tf_Osf#UzHvW0C0@l;Bsx_~>cLxWt)-&|aVS#s_=WM7d>9 z7=4w;OV<9`FFt3If$JD=y&Cs9aJQpLG&PrXwH&F>2Z#H+y1(?6q6Fy=`?&1*h_ZMK zIf)F^Hx0MR-r!P*^ijN^5g}TDfzLeN^J)72-dDB^X>Zn=LX=q2GyvNidF*MnYx=oQ zdGIOM_)M2HA;Mcd^2C71xR=w<*kG%v*DS>A99W#{2WL2c@go_FH?3Jse+Ewb=0J6U+oQ=Il35(>+FWuXdQl~^I&1?CqO3?7hLW9M#o0xwA+b+pkTH1VH9x#w6Z82>QTfx0$RDH3Pw0i-=wl(?zeL?0q{0G-kd` zK4#(~tiv@8TqJ1_GG3bH{Cwnr{u_sup&t)zxFP-ru$4^ITzIz1)X?Vlp$Vhg{ZMA; z#&wT5QmZ?16qbSbuSqQhAc7BFlJ}okPS+z2NsbpBpU%ps#T(3>uvVr7@zpC&vizSp z-bQ^&28nl5dKLDyJ5g5?ur9T%zaspNzT=Yi!e!H{hMcWT={b()_w^V1jupu_-suGC zk3NN%@dSGyzviFOQFJbKZU{;?4m@#k5^HjG#6s6yd!soHz-mM(4~cg5G6)i=aV3B> znJON4cAHaz`&XY&8{Z(Hcotgf=iQ=vcvXkn>$)PKjQ%QU1T@BNKxmo~2p}cfDk+Yj zMQZUC-CHXmuoyJ~hH;WN;OF3U-Dp7TuO_PpoPKV6AQx22N`uk-0s^qdbIxClME6t^ zdn0cBKC#Qia&1(UV9Ht@=5{PC4y70t-~ zRXE@W;?zQj7c%7ic?KHjn4#kXW;C~}NfOjBdGAk?ID8*&-;(GQqvi{LYdk7$flQ7; z`?ii8A{O2kA{XST5A+&voNccJR)LeNfybp6nwQS)yR$|RXYc65z(ei?VVumVWMvkN zn_ZODjp?t?FMap-3*)m|m{_Ta0H5#1NM+A@7m^X2%sePWqXB zhDK}RMT`E~yG@mX?MRbrP^nNE(#Goc_|~g)1Fms?UOPtPu-DV38~=c7rQ_f8 zIbseJUnYr1d+j0$pMAz0DHfa`S6Y^`eU8NLjri4ARmAy9S!7vE#Oi{%GD*F*M9NIy z#EQ6PMVeVdvw-h#TNlC<6w+5Va_TzlBTek9XK5ts{(_~GuTUNKMMH#rMyo^v21$mU z;aaPqTIFNVsZ!$;Z1m%uzBZWFKLCfN@uX7h%I;gKxs?};M8F)Qffft`d;^a$LK#?^yrTm2rGJ5tJ-5|jXi?J8%C#V}F~V}8 zIC4}Bi^~z3azmb8zD)=%mE#;Ms)4IBoT5R}ydJc~cfEAWu(TPf_G+|7gcFftS^{z~ zdUKq{cQIB~{{AX)V*P2qX=h-iRMd5ZdZ(|L3hkoI zh*6;?#|e$sj%)KGxyu@I&{4S1kEcdyne2rBvTChy^+@;Zlfd#kiE)WG^&TD=Q+=|a zP5UPJfr6UoQ46_m?I!r)_sW5ivc@CcoM2NUKgjL6r<&{YA@&P%;K@R~U`P~DBP;Nh z-BW#CFA<}w5II#xVp9(4Q&EC$7O|A@|VjF&Dihb*@O+{~B z@3{{3AoWUVRYK^ulze}?J<>!CwN`uS-8VPRaO~6UKR`f2d5N{+gp?D|^8yZp6?(1| z?ZLC({B@w+BQKq!FU0f5lrkdXka);GybMC4yix)TiiDOGSG=(_Hh zc2x?}hx{zhFx7Sf0z!_W6=2EK22{|{i)G5EUI+w;^b3A&9ZkX>X*lGbCNdKF3&N72 zPnd2f%AGKNk1U=y5&zB60hYfH(C7g!e#ENce*9OuISttmQ<#U5o^p5al-_*gwvld? ziw=#UsyqPiAs;+vUBi4R;6K1=WaIxC<=GbnG=b&=S>`vXsa6Nu?~qHO2b}smUkBnY z5aykkNbpt7AAXMZD5<(awW9ryu1@m#>%v#PUn->vB5m+o#r*(Tf_V- zo}$0KVY--IUMMO|3@mp_uM z44n$5!B1S>j__Na{C0U5G0OfvNREEwDj&-IEVk#fAcrK$`$t02EUz=H$)1Ab3$_~2 zTj^%)x=i}%G@`?kl(CqFAqI70o*;4k)x{X=m)0Go3wM+5T)upaFCQ*u#n-WOC}m^^1hKFmpJ(p&wRRR`~(9)zXx2!O`-t$loH}em~yyqk}q; zc?0n4id&y@_9g7OZu2PbbzqmG@= z_=h#Lxf}Ex;qPRl3?gV{4}qkjJcbwLSW}ULxl`9}0%ucWUI%$88ov1y5 zQ-O?;GrFSQjaqL+jI_T+$WEEQw%5zM?pLUey%W#rU4$qTN}%dWhMm!QOLZS8P{_XM zrqXJu7j>HAwryE>S1wQkK9XY5Ku4t~txM__fwmGfQ`yNs$J8vspuQ!%lkDLgC3jzQ zw(-}l&7sgj(ZDRj%Zz&97-Ax|!Qs7JhRP0<`DG4kvIXKQSl zcz41q`%Y4+Sd>8CB}?=m&F1~WtASphA<|1Af5~LAugj1i(cR$bpFS)>&!LbqyXeLn zBdc(4<6f7!zwMS&G(%tNPfA#9I7w<*7*W{aq&wycfO-pC{;oDNJI~bKvbIuxnEZ=v*8;U}OC|X7%1Bsg?$z%i zimj`@v}$uVpfg(hWeDxNan^8XOV^tyQDtfkf-Wx3BIJODGzS&~?J624maf`;U{k3b z+yCMU-9ddS8O>8(RmRUCeg0$PDT5#DEoOND*xzpMWm@);L!5C8he?E~+j;4%bIiCO z5{-!urgwN>qY6LNJY4AZBjY|QjSZ3MN4XvFE}t<9dl>0^cOZHc$q6(+erb!KS{+@r z#L`uC#2M@>O9+9$ud!_F{nyn4X;b=5JV+S_!#q|c4qaQ~pXe6g%s6W|U5MUqW>G7W zGp3wZFIeP9z0{kv9rA2_NSA(HtFbpvIR<)Yc3U;G{pm+9sQ$hwct>^UNFh$Oto8cj zwPe}74oH6uP$04kV3H3O%pVy^B6+Z=(E#m8@}$$`?SS?xep#1%{CGIK;oQ(BdcD)b z_ka;)uoY5dsJt&%ILnstB9KZ$3ZfhGgvUAiy7Y_;Iu-Ap>6a?Jb!uoN=ky!aI{%bE zW2qsc(dkVukMWn!@wy+8hj^PfnH^sDGVV|mVO3hqv>(W2e9#qM$v){dO6XG&= z&=|KjdF==8b?H60sB(Aqef<1uqU{>?M+y-Oprly|ZBY~Gy8xLzK!@kz2 z1ym}|Y)rTU57T=dfn8?*>dTwymWHZ)%5sw486QZ1vyfauCTdHaR~=D&KH8f|r-1Rr zzK@pgeHFfrXmPuTQ>{W5BkzVo!G;L+fc3(`tiLLcCAt!0i0R026QhN)dFPz9tS~u; z2(iag+@`$pPpf03l~u`sJ5_1V)5yi56nc&9d@j0rIpo>OU?b%<{7;*vRwSQU2C-l5 zVNsOB^5x#lRG#@7=j>#evBiGVpP$zEjP znaJopujwLO<%A|{EsRsfc`UdGpIs48BzL0vmaY4(I-Ufv=|d;dZkLzOJhoCDg2WtG zx?c6QA|-^0hEjKp00nu|jN}3QcUgZ-Kf*`r)5cjd5}=6xt0~&Imaq6Na+2LLvF)^2qnp)zV zl2l@dug{7|I5I)279acqS5gLjkYQf>k}FZdj)@tE67)*^KYyp+2-Y>XMIGbh;$e4F z`^9QyfdC{zMb#I-rwN{zk7k52Jm@eWK=R`i3ln*nDz_exY+`V11UC~cQn(ZKuZV-%{b17~{@13T+SUr-o;B zV72>*_%6dpQ;8+T1s#lKi1|16AL}(C$QHrz3jOynhj_%IixcO~`r<6%y7tzzpG#w< z=J6Uw8T%1(50j{;@K_JI1^!BSU#UYk=rE5beYmrQry_47eb?&j#rPyrSfJLmvV^qc zPM)3%oPy^WIN^UW1O9IWYq^QEkO_R44pf$5qC!cyAlINOm=6Llc15xDKFV75U=6fm zj+kvY%D;&Uf|h;K!rM_S8Mf&t*KyfhVm~6(D_q@j+?lKL3kugLM2zFeAH{94Hnh%n z|CX%yA~?+&VwSPEOMl$-_k?C!Nd#rtID=VYb5(!Z5fM(9mlqOHZ3+#}X<^M!^Uh?I zZDI3{u5I1A4Sznqy|ShBQH=E3Ci>g^{`xL2#iXB4~gKVm-SckOp@NU6kX`O!w8 zc=8@5=SUTrR@1=h7@j0B2M3@$`Q%N@iDhyqVwkTGa4+P1<_KKTzWYX|wpC~&`n$%L z*j?2C;L~3cPA&G5Iadnvd9`uJ8@Ph_H4ta+m3XgcjXxs5!1Qy)<#dr_xj^SqsoA)M zaitwzrMom!fKq2xqC;H#hKga2*gBGyrHq#t)-R@;E?INQbJst`D=l+9K0_1hwM}0O z@k?#iJt2FsZhs;&**@~92MEXf1F%j-zb9`LIc~dUTeT7^UoVktbD0usJnAYsNeVWJ zAQqWT%3x820D5T+HU5JryI-M}sU)CA!T7V(3AiZ|DuPElhqZTS5z&usfAYUsxRE2> z>mQN3OQ6jBo>e?VM-8=`MGuz|6QGCu>90v%52p;WPb#LWkNb4t&}_rE@hk~37#ssY z)Ji1Er2YduyfXd=a5uZ=BNS!>S}gT*Ox4!CVu=M{NldS`9q+U;*-Eb6?7O1X1t`7# zPF=Sg9Q1e<*L_TINF%yvTbDN=WU!-tR&Sn@A3@lr%loEMu)zW2)AtFmFz#7DpC-80Xz&WG2ShjMP2!XqG77 z{4*C0oLDA@CO>A0{k;9<2fr3XHK}&9!_c>Fw39B661qH_b6*}lrc@@eE)OWFXQ|H2 zf{*u1w%%;K6Ed^>1>At|FS+p08tVM#v;SYOEUw8kgdNN7*LuP5qD_8(lr^ReZ%@@W>bck6i3|mj? zc`J6h71tkaCX}j$lV^VXLtR^DT1+L~H z&Zo5~Gvy{}GKI!5kD!!q8hZD9vt&)|J{BLm?(waiL-EGum9PHf*CN$6ET1r%>Q&^L z;+_k5$@<|{l8yK~LR|BcYrhZHQgd*M+Wg5ET*P}8qW$CjEP7L?m1qu3d-!RM49_1Y z{J^Bo7+F{%?dUSoo@E+EXOB02ncJ%U4?0QuT`k!~)40CN%1VrpKqK-siYD`&O$TAU zH=a;b0Msa*_^Bg0zJ&~=+YU$G4}h!mbvB*Y z4gW^PmakzUg~v|is8|0T$tDPZ6|A)5cORxlY)NREfQ9|6TY_Y~OF%<7b>()yj$Hio zLjgm{^05HlMy5=i!WC8g)`jz|Lqfpu_{%doiPu1w84z6-5UT&XG1}~ysLFn;XRFr3 zHgHTm#yJUu-179~iVOgj&t7hoQ>8xKZCcuRg|zK1q7y2}c~OC0&^9k-5vv*7Hj`#{ zr_1zjs?Scgb&8!&{$&(8f)K9@S15X&mNm+A9R)Ck6cZWf}+C>%|+Gic%E# zlR2?8{oAAwX<=2^GH*q3-0Kl|n=gA#1tGUTtsX=*svQ*cILxQ#q0MI<>hwm|?0rEs zz2zB-#QIOs27bSO8K+| zkK2sN-CKdlGkRO$^`VS5b$0gcy{R*_PHK9}eMJn^lFWj{o__ZB__zAzvnuY#Oa+y; zBZK`Q>|Ij#QotJ!X9r5e??&6rIK}e4%%Jx@;KXP8u%!rxs zdq8o`!t#Q3A9qs$DCG}$M91JF?~5bC?sCXf^yOwVPu(BU`gqSU za)h1D_b+MDZ`o;qq#qtuC&t|Nw=mgYW28Y%1At8{_xp!>=qK=Pkio?d{!sx&E|-s` z4h1jmKuU>vwOJ&Xi#4Qs4JVmn906OR;;Ls~vCI4&@vbqV^6W!{?#XyR?mCqs-%^PI zMv0oc4|O>RxQsTg2-0n=(m!Krb*uCOAqxyFGWg)W%tbWj#`|I(l7I&e>ZDC3|ms;qs1{ZF<`A&ihns1x5(cgYhY!3bihC zb$_5Up`F|=J?Q2sia6*r|FjtzEABq3GsOT;qd|;kA8dte@$2Fy5J2G z4vr+I&EaghQeu0qrB*fH*^$3Q^dlVQd)}6qf9jxZF=@C{Q8B#iof|o;)IxOg!4YHoQYk^{gR>&_qs8V&JIN1pk?dm z_jM~|LxCF}%6z$a-#6Z;4QzLOMX+ZGf^s3+L06zc!x>>okjeGIRXw(7?5~$uvaxQI zWOFnpb2LMRnZSt@6ps%w!6!((EB622tILKTRWRLXXus&*pf2l?p-Sat`bh7X+oHBS zjpY5N2K=6N86gs~|A=0MZZ9|_(vNget-zczoX}b-f9*iTz~Js@oqSU5uVZIu`wM-& z5R*sr^poGTpG#B!c}G;G+4GKeOpEe9Ii<=k?FA4+9ZM4q!y*ic!5yk4Qr*{63&vZB ztbR)EZSRkYX(c!}CE9GrFqI%xC!-k`6^Los+W$gQr*r8f$u_1McMnUs+}#R73chtL z=!-2|jZ|5Sis@*aqTgX>AKtBRq=+qZu)-hFkcV^9c;If^R)W~fg+nBxnu;gXXlo7r OM|bi61aA`joBMBm>`X-f diff --git a/other/7719370.png b/other/7719370.png deleted file mode 100644 index 68a35e650189e6eee02727a049976a7f99652b58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158793 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

_&! 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%0AvcBfE14PnLAYA6{`ax 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Ϣ_Z@= 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 Date: Sat, 22 Sep 2018 11:16:26 +0800 Subject: [PATCH 101/136] auto commit --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 116e2a4b..258fa75d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ | 算法[:pencil2:](#pencil2-算法) | 操作系统[:computer:](#computer-操作系统)|网络[:cloud:](#cloud-网络) | 面向对象[:couple:](#couple-面向对象) |数据库[:floppy_disk:](#floppy_disk-数据库)| Java [:coffee:](#coffee-java)| 系统设计[:bulb:](#bulb-系统设计)| 工具[:hammer:](#hammer-工具)| 编码实践[:speak_no_evil:](#speak_no_evil-编码实践)| 后记[:memo:](#memo-后记) |
+


@@ -195,41 +196,41 @@ 笔者将自己实现文档转换功能提取出来,方便大家在需要将本地 Markdown 上传到 Github,或者制作项目 README 文档时生成目录时使用:[GFM-Converter](https://github.com/CyC2018/GFM-Converter)。 -#### Statement - -本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) - #### Logo Power by [logomakr](https://logomakr.com/). +#### Statement + +本仓库不参与商业行为,不向读者收取任何费用。(This repository is not engaging in business activities, and does not charge readers any fee.) + #### Acknowledgements 感谢以下人员对本仓库做出的贡献,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与笔者联系。 - +​ - +​ - +​ - +​ - +​ - +​ - +​ - +​ #### License From 127f7559fbfd8392e73f659c12850081036a192e Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 22 Sep 2018 15:06:41 +0800 Subject: [PATCH 102/136] auto commit --- notes/Java 容器.md | 2 +- notes/Leetcode 题解.md | 8 ++++---- notes/分布式.md | 1 - notes/攻击技术.md | 2 +- notes/计算机操作系统.md | 2 +- notes/集群.md | 5 ----- pics/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png | Bin 0 -> 21504 bytes 7 files changed, 7 insertions(+), 13 deletions(-) create mode 100644 pics/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png diff --git a/notes/Java 容器.md b/notes/Java 容器.md index e42a42f0..3a7343f9 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -25,7 +25,7 @@ ## Collection -

+

### 1. Set diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index e128e1d3..def70c60 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2415,7 +2415,8 @@ public int climbStairs(int n) { 定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。 由于不能抢劫邻近住户,因此如果抢劫了第 i 个住户那么只能抢劫 i - 2 或者 i - 3 的住户,所以 -dp[i] = max(dp[i-1], dp[i-2] + nums[i])
+ +

```java public int rob(int[] nums) { @@ -2427,7 +2428,6 @@ public int rob(int[] nums) { } return pre1; } - ``` **强盗在环形街区抢劫** @@ -2505,9 +2505,9 @@ public int minPathSum(int[][] grid) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0) { - if (j>0) dp[j] = dp[j - 1]; + dp[j] = dp[j - 1]; } else { - if (j>0) dp[j] = Math.min(dp[j - 1], dp[j]); + dp[j] = Math.min(dp[j - 1], dp[j]); } dp[j] += grid[i][j]; } diff --git a/notes/分布式.md b/notes/分布式.md index d2b2f974..2adba608 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -335,5 +335,4 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。 - [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) - [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) - [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) -- [ACID](https://en.wikipedia.org/wiki/ACID_(computer_science)) diff --git a/notes/攻击技术.md b/notes/攻击技术.md index 31eeaaa4..115456cb 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -111,7 +111,7 @@ http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName 这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务器端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。 -透过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作。 +通过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作。 ## 防范手段 diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index c0c4364e..00d26160 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -879,7 +879,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。 -为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面时最近最久未访问的。 +为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。 因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。 diff --git a/notes/集群.md b/notes/集群.md index 111495c3..cd2af078 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -116,11 +116,6 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 ### 3. 反向代理服务器 -首先了解一下正向代理与反向代理的区别: - -- 正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端; -- 反向代理:发生在服务器端,用户不知道反向代理的存在。 - 反向代理服务器位于源服务器前面,用户的请求需要先经过反向代理服务器才能到达源服务器。反向代理可以用来进行缓存、日志记录等,同时也可以用来做为负载均衡服务器。 在这种负载均衡转发方式下,客户端不直接请求源服务器,因此源服务器不需要外部 IP 地址,而反向代理需要配置内部和外部两套 IP 地址。 diff --git a/pics/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png b/pics/VP6n3i8W48Ptde8NQ9_0eSR5eOD6uqx.png new file mode 100644 index 0000000000000000000000000000000000000000..d2559cf3c8acb1656a802e9e155720145b96486a GIT binary patch literal 21504 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 Z3HBAIVYA@|hIH6ayGYCC%3sa@e*ppvRUQBU literal 0 HcmV?d00001 From b57f404cd400ae7de80d8c081db73943e2f90f81 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 22 Sep 2018 15:46:59 +0800 Subject: [PATCH 103/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 notes/CyC 学习交流群 问题汇总.md diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md deleted file mode 100644 index 806d48d0..00000000 --- a/notes/CyC 学习交流群 问题汇总.md +++ /dev/null @@ -1,16 +0,0 @@ - -* [0. 进程内存空间中,堆和栈的区别](#0-进程内存空间中,堆和栈的区别) - - - -# 0. 进程内存空间中,堆和栈的区别 - -> C++ - -堆:动态、malloc()、new、链式分配、向上生长;栈:函数调用、编译器分配回收、向下生长。 - -https://www.cnblogs.com/sunziying/p/6510030.html - -By @CyC - ---- From 3ab4f89da6d560e3d641d09930eb8a16e053e870 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 22 Sep 2018 20:35:51 +0800 Subject: [PATCH 104/136] auto commit --- notes/CyC 学习交流群 问题汇总.md | 16 ++++++++++++++++ notes/Leetcode 题解.md | 1 - notes/Redis.md | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 notes/CyC 学习交流群 问题汇总.md diff --git a/notes/CyC 学习交流群 问题汇总.md b/notes/CyC 学习交流群 问题汇总.md new file mode 100644 index 00000000..806d48d0 --- /dev/null +++ b/notes/CyC 学习交流群 问题汇总.md @@ -0,0 +1,16 @@ + +* [0. 进程内存空间中,堆和栈的区别](#0-进程内存空间中,堆和栈的区别) + + + +# 0. 进程内存空间中,堆和栈的区别 + +> C++ + +堆:动态、malloc()、new、链式分配、向上生长;栈:函数调用、编译器分配回收、向下生长。 + +https://www.cnblogs.com/sunziying/p/6510030.html + +By @CyC + +--- diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index def70c60..3e19a632 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -3086,7 +3086,6 @@ public int findTargetSumWays(int[] nums, int S) { int W = (sum + S) / 2; int[] dp = new int[W + 1]; dp[0] = 1; - Arrays.sort(nums); for (int num : nums) { for (int i = W; i >= num; i--) { dp[i] = dp[i] + dp[i - num]; diff --git a/notes/Redis.md b/notes/Redis.md index 58320dfa..fe34c7e7 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -355,7 +355,7 @@ List 是一个双向链表,可以通过 lpop 和 lpush 写入和读取消息 ## 会话缓存 -在分布式场景下具有多个应用服务器,可以使用 Redis 来统一存储这些应用服务器的会话信息。 +可以使用 Redis 来统一存储多台应用服务器的会话信息。 当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。 From bb1d703412d4a00daeafdc8d5b8fc59d22b18009 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 00:56:49 +0800 Subject: [PATCH 105/136] auto commit --- notes/Java 容器.md | 2 +- notes/Leetcode 题解.md | 9 ++++----- notes/Redis.md | 2 +- notes/分布式.md | 1 - notes/攻击技术.md | 2 +- notes/计算机操作系统.md | 2 +- notes/设计模式.md | 2 +- notes/集群.md | 5 ----- 8 files changed, 9 insertions(+), 16 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index e42a42f0..3a7343f9 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -25,7 +25,7 @@ ## Collection -


+

### 1. Set diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index e128e1d3..3e19a632 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2415,7 +2415,8 @@ public int climbStairs(int n) { 定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。 由于不能抢劫邻近住户,因此如果抢劫了第 i 个住户那么只能抢劫 i - 2 或者 i - 3 的住户,所以 -dp[i] = max(dp[i-1], dp[i-2] + nums[i])
+ +

```java public int rob(int[] nums) { @@ -2427,7 +2428,6 @@ public int rob(int[] nums) { } return pre1; } - ``` **强盗在环形街区抢劫** @@ -2505,9 +2505,9 @@ public int minPathSum(int[][] grid) { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i == 0) { - if (j>0) dp[j] = dp[j - 1]; + dp[j] = dp[j - 1]; } else { - if (j>0) dp[j] = Math.min(dp[j - 1], dp[j]); + dp[j] = Math.min(dp[j - 1], dp[j]); } dp[j] += grid[i][j]; } @@ -3086,7 +3086,6 @@ public int findTargetSumWays(int[] nums, int S) { int W = (sum + S) / 2; int[] dp = new int[W + 1]; dp[0] = 1; - Arrays.sort(nums); for (int num : nums) { for (int i = W; i >= num; i--) { dp[i] = dp[i] + dp[i - num]; diff --git a/notes/Redis.md b/notes/Redis.md index 58320dfa..fe34c7e7 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -355,7 +355,7 @@ List 是一个双向链表,可以通过 lpop 和 lpush 写入和读取消息 ## 会话缓存 -在分布式场景下具有多个应用服务器,可以使用 Redis 来统一存储这些应用服务器的会话信息。 +可以使用 Redis 来统一存储多台应用服务器的会话信息。 当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。 diff --git a/notes/分布式.md b/notes/分布式.md index d2b2f974..2adba608 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -335,5 +335,4 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。 - [What is CAP theorem in distributed database system?](http://www.colooshiki.com/index.php/2017/04/20/what-is-cap-theorem-in-distributed-database-system/) - [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/) - [Paxos By Example](https://angus.nyc/2012/paxos-by-example/) -- [ACID](https://en.wikipedia.org/wiki/ACID_(computer_science)) diff --git a/notes/攻击技术.md b/notes/攻击技术.md index 31eeaaa4..115456cb 100644 --- a/notes/攻击技术.md +++ b/notes/攻击技术.md @@ -111,7 +111,7 @@ http://www.examplebank.com/withdraw?account=AccoutName&amount=1000&for=PayeeName 这种恶意的网址可以有很多种形式,藏身于网页中的许多地方。此外,攻击者也不需要控制放置恶意网址的网站。例如他可以将这种地址藏在论坛,博客等任何用户生成内容的网站中。这意味着如果服务器端没有合适的防御措施的话,用户即使访问熟悉的可信网站也有受攻击的危险。 -透过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作。 +通过例子能够看出,攻击者并不能通过 CSRF 攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户浏览器,让其以用户的名义执行操作。 ## 防范手段 diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index c0c4364e..00d26160 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -879,7 +879,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU 将最近最久未使用的页面换出。 -为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面时最近最久未访问的。 +为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。 因为每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。 diff --git a/notes/设计模式.md b/notes/设计模式.md index c177ff92..e990677e 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -95,7 +95,7 @@ private static Singleton uniqueInstance = new Singleton(); 只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了实例化多次 uniqueInstance。 -但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,即使 uniqueInstance 已经被实例化了。这会让线程阻塞时间过程,因此该方法有性能问题,不推荐使用。 +但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,即使 uniqueInstance 已经被实例化了。这会让线程阻塞时间过长,因此该方法有性能问题,不推荐使用。 ```java public static synchronized Singleton getUniqueInstance() { diff --git a/notes/集群.md b/notes/集群.md index 111495c3..cd2af078 100644 --- a/notes/集群.md +++ b/notes/集群.md @@ -116,11 +116,6 @@ HTTP 重定向负载均衡服务器使用某种负载均衡算法计算得到服 ### 3. 反向代理服务器 -首先了解一下正向代理与反向代理的区别: - -- 正向代理:发生在客户端,是由用户主动发起的。比如翻墙,客户端通过主动访问代理服务器,让代理服务器获得需要的外网数据,然后转发回客户端; -- 反向代理:发生在服务器端,用户不知道反向代理的存在。 - 反向代理服务器位于源服务器前面,用户的请求需要先经过反向代理服务器才能到达源服务器。反向代理可以用来进行缓存、日志记录等,同时也可以用来做为负载均衡服务器。 在这种负载均衡转发方式下,客户端不直接请求源服务器,因此源服务器不需要外部 IP 地址,而反向代理需要配置内部和外部两套 IP 地址。 From 5640334d7bd91f335a704d2df485c5486b96ab1e Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 10:06:19 +0800 Subject: [PATCH 106/136] auto commit --- notes/设计模式.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index e990677e..f5029ec8 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -221,7 +221,7 @@ public enum Singleton { 该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 -该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止实例化第二个对象的代码。但是该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 +该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止多次实例化的代码。该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 ### Examples From a3b67328688a4eaba1243d509dc511ae7e5fa0c0 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 13:00:24 +0800 Subject: [PATCH 107/136] auto commit --- notes/Java 基础.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index eb3572cd..a2cf6532 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -288,6 +288,7 @@ Java 的参数是以值传递的形式传入方法中,而不是引用传递。 ```java public class Dog { + String name; Dog(String name) { @@ -347,7 +348,9 @@ class PassByValueExample { ## float 与 double -1.1 字面量属于 double 类型,不能直接将 1.1 直接赋值给 float 变量,因为这是向下转型。Java 不能隐式执行向下转型,因为这会使得精度降低。 +Java 不能隐式执行向下转型,因为这会使得精度降低。 + +1.1 字面量属于 double 类型,不能直接将 1.1 直接赋值给 float 变量,因为这是向下转型。 ```java // float f = 1.1; @@ -588,10 +591,11 @@ System.out.println(InterfaceExample.x); ## super - 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。 -- 访问父类的成员:如果子类重写了父类的中某个方法的实现,可以通过使用 super 关键字来引用父类的方法实现。 +- 访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。 ```java public class SuperExample { + protected int x; protected int y; @@ -608,6 +612,7 @@ public class SuperExample { ```java public class SuperExtendExample extends SuperExample { + private int z; public SuperExtendExample(int x, int y, int z) { @@ -659,7 +664,6 @@ SuperExtendExample.func() ## 概览 ```java -public final native Class getClass() public native int hashCode() @@ -669,6 +673,10 @@ protected native Object clone() throws CloneNotSupportedException public String toString() +public final native Class getClass() + +protected void finalize() throws Throwable {} + public final native void notify() public final native void notifyAll() @@ -678,8 +686,6 @@ public final native void wait(long timeout) throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException public final void wait() throws InterruptedException - -protected void finalize() throws Throwable {} ``` ## equals() @@ -806,6 +812,7 @@ public int hashCode() { ```java public class ToStringExample { + private int number; public ToStringExample(int number) { @@ -849,7 +856,7 @@ public class CloneExample { private int b; @Override - protected CloneExample clone() throws CloneNotSupportedException { + public CloneExample clone() throws CloneNotSupportedException { return (CloneExample)super.clone(); } } @@ -878,7 +885,7 @@ public class CloneExample implements Cloneable { private int b; @Override - protected Object clone() throws CloneNotSupportedException { + public Object clone() throws CloneNotSupportedException { return super.clone(); } } @@ -1052,6 +1059,7 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和 ```java public class A { + private int x; // 实例变量 private static int y; // 静态变量 @@ -1080,6 +1088,7 @@ public abstract class A { ```java public class A { + private static int x; private int y; @@ -1118,6 +1127,7 @@ public class A { ```java public class OuterClass { + class InnerClass { } From 4a9c4a539133caec2bbac09a827c513f907015ff Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 20:34:40 +0800 Subject: [PATCH 108/136] auto commit --- notes/Socket.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/notes/Socket.md b/notes/Socket.md index 7cb4fbf0..ddc47f56 100644 --- a/notes/Socket.md +++ b/notes/Socket.md @@ -5,7 +5,6 @@ * [I/O 复用](#io-复用) * [信号驱动 I/O](#信号驱动-io) * [异步 I/O](#异步-io) - * [同步 I/O 与异步 I/O](#同步-io-与异步-io) * [五大 I/O 模型比较](#五大-io-模型比较) * [二、I/O 复用](#二io-复用) * [select](#select) @@ -83,16 +82,14 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *

-## 同步 I/O 与异步 I/O - -- 同步 I/O:应用进程在调用 recvfrom 操作时会阻塞。 -- 异步 I/O:不会阻塞。 - -阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O 都是同步 I/O,虽然非阻塞式 I/O 和信号驱动 I/O 在等待数据阶段不会阻塞,但是在之后的将数据从内核复制到应用进程这个操作会阻塞。 - ## 五大 I/O 模型比较 -前四种 I/O 模型的主要区别在于第一个阶段,而第二个阶段是一样的:将数据从内核复制到应用进程过程中,应用进程会被阻塞。 +- 同步 I/O:将数据从内核缓冲区复制到应用进程缓冲区的阶段,应用进程会阻塞。 +- 异步 I/O:不会阻塞。 + +阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O 都是同步 I/O,它们的主要区别在第一个阶段。 + +非阻塞式 I/O 、信号驱动 I/O 和异步 I/O 在第一阶段不会阻塞。

@@ -299,7 +296,7 @@ epoll 的描述符事件有两种触发模式:LT(level trigger)和 ET(ed ### 1. select 应用场景 -select 的 timeout 参数精度为 1ns,而 poll 和 epoll 为 1ms,因此 select 更加适用于实时要求更高的场景,比如核反应堆的控制。 +select 的 timeout 参数精度为 1ns,而 poll 和 epoll 为 1ms,因此 select 更加适用于实时性要求比较高的场景,比如核反应堆的控制。 select 可移植性更好,几乎被所有主流平台所支持。 @@ -309,11 +306,11 @@ poll 没有最大描述符数量的限制,如果平台支持并且对实时性 ### 3. epoll 应用场景 -只需要运行在 Linux 平台上,并且有非常大量的描述符需要同时轮询,而且这些连接最好是长连接。 +只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。 需要同时监控小于 1000 个描述符,就没有必要使用 epoll,因为这个应用场景下并不能体现 epoll 的优势。 -需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且epoll 的描述符存储在内核,不容易调试。 +需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。 # 参考资料 From e89b0aab31c7c8a22c688c24a983becc4ff3c8da Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 20:42:29 +0800 Subject: [PATCH 109/136] auto commit --- notes/Java IO.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/notes/Java IO.md b/notes/Java IO.md index a2dd668b..e137fb7b 100644 --- a/notes/Java IO.md +++ b/notes/Java IO.md @@ -284,10 +284,6 @@ public static void main(String[] args) throws IOException { # 七、NIO -- [Java NIO Tutorial](http://tutorials.jenkov.com/java-nio/index.html) -- [Java NIO 浅析](https://tech.meituan.com/nio.html) -- [IBM: NIO 入门](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html) - 新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。 ## 流与块 @@ -343,7 +339,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重

-② 从输入通道中读取 5 个字节数据写入缓冲区中,此时 position 移动设置为 5,limit 保持不变。 +② 从输入通道中读取 5 个字节数据写入缓冲区中,此时 position 为 5,limit 保持不变。

@@ -612,6 +608,8 @@ NIO 与普通 I/O 的区别主要有以下两点: - Eckel B, 埃克尔, 昊鹏, 等. Java 编程思想 [M]. 机械工业出版社, 2002. - [IBM: NIO 入门](https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html) +- [Java NIO Tutorial](http://tutorials.jenkov.com/java-nio/index.html) +- [Java NIO 浅析](https://tech.meituan.com/nio.html) - [IBM: 深入分析 Java I/O 的工作机制](https://www.ibm.com/developerworks/cn/java/j-lo-javaio/index.html) - [IBM: 深入分析 Java 中的中文编码问题](https://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/index.htm) - [IBM: Java 序列化的高级认识](https://www.ibm.com/developerworks/cn/java/j-lo-serial/index.html) From 5eaf1daec131ee9849ffc6e6bc0f47c6a44d08b3 Mon Sep 17 00:00:00 2001 From: Lin Zhu Date: Sun, 23 Sep 2018 10:55:46 -0400 Subject: [PATCH 110/136] =?UTF-8?q?=E4=B8=8A=E5=8D=87=E5=AD=90=E5=BA=8F?= =?UTF-8?q?=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 找到第一个比x大的,更新那个值,记录更小的tail Reference: (Leetcode 300)(https://leetcode.com/problems/longest-increasing-subsequence/discuss/74824/JavaPython-Binary-search-O(nlogn)-time-with-explanation) --- notes/Leetcode 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 3e19a632..bdf03c8d 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2781,7 +2781,7 @@ return ret; 定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素。对于一个元素 x, - 如果它大于 tails 数组所有的值,那么把它添加到 tails 后面,表示最长递增子序列长度加 1; -- 如果 tails[i-1] < x <= tails[i],那么更新 tails[i-1] = x。 +- 如果 tails[i-1] < x <= tails[i],那么更新 tails[i] = x。 例如对于数组 [4,3,6,5],有: From 3a604c23e82a5d4a0285f0e4643c2ee0769bb4e1 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 23 Sep 2018 22:56:22 +0800 Subject: [PATCH 111/136] auto commit --- notes/HTTP.md | 95 ++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index ef6faf87..f9abd238 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -24,9 +24,9 @@ * [响应首部字段](#响应首部字段) * [实体首部字段](#实体首部字段) * [五、具体应用](#五具体应用) + * [连接管理](#连接管理) * [Cookie](#cookie) * [缓存](#缓存) - * [连接管理](#连接管理) * [内容协商](#内容协商) * [内容编码](#内容编码) * [范围请求](#范围请求) @@ -44,14 +44,14 @@ * [二进制分帧层](#二进制分帧层) * [服务端推送](#服务端推送) * [首部压缩](#首部压缩) -* [八、GET 和 POST 比较](#八get-和-post-比较) +* [八、HTTP/1.1 新特性](#八http11-新特性) +* [九、GET 和 POST 比较](#九get-和-post-比较) * [作用](#作用) * [参数](#参数) * [安全](#安全) * [幂等性](#幂等性) * [可缓存](#可缓存) * [XMLHttpRequest](#xmlhttprequest) -* [九、HTTP/1.0 与 HTTP/1.1 的区别](#九http10-与-http11-的区别) * [参考资料](#参考资料) @@ -102,7 +102,7 @@ URI 包含 URL 和 URN,目前 WEB 只有 URL 比较流行,所以见到的基 POST 主要用来传输数据,而 GET 主要用来获取资源。 -更多 POST 与 GET 的比较请见第八章。 +更多 POST 与 GET 的比较请见第九章。 ## PUT @@ -303,6 +303,25 @@ CONNECT www.example.com:443 HTTP/1.1 # 五、具体应用 +## 连接管理 + +

+ +### 1. 短连接与长连接 + +当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源。如果每进行一次 HTTP 通信就要新建一个 TCP 连接,那么开销会很大。 + +长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。 + +- 从 HTTP/1.1 开始默认是长连接的,如果要断开连接,需要由客户端或者服务器端提出断开,使用 `Connection : close`; +- 在 HTTP/1.1 之前默认是短连接的,如果需要使用长连接,则使用 `Connection : Keep-Alive`。 + +### 2. 流水线 + +默认情况下,HTTP 请求是按顺序发出的,下一个请求只有在当前请求收到响应之后才会被发出。由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。 + +流水线是在同一条长连接上发出连续的请求,而不用等待响应返回,这样可以避免连接延迟。 + ## Cookie HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。 @@ -420,7 +439,7 @@ Session 可以存储在服务器上的文件、数据库或者内存中。也可 HTTP/1.1 通过 Cache-Control 首部字段来控制缓存。 -**(一)禁止进行缓存** +**3.1 禁止进行缓存** no-store 指令规定不能对请求或响应的任何一部分进行缓存。 @@ -428,7 +447,7 @@ no-store 指令规定不能对请求或响应的任何一部分进行缓存。 Cache-Control: no-store ``` -**(二)强制确认缓存** +**3.2 强制确认缓存** no-cache 指令规定缓存服务器需要先向源服务器验证缓存资源的有效性,只有当缓存资源有效才将能使用该缓存对客户端的请求进行响应。 @@ -436,7 +455,7 @@ no-cache 指令规定缓存服务器需要先向源服务器验证缓存资源 Cache-Control: no-cache ``` -**(三)私有缓存和公共缓存** +**3.3 私有缓存和公共缓存** private 指令规定了将资源作为私有缓存,只能被单独用户所使用,一般存储在用户浏览器中。 @@ -450,7 +469,7 @@ public 指令规定了将资源作为公共缓存,可以被多个用户所使 Cache-Control: public ``` -**(四)缓存过期机制** +**3.4 缓存过期机制** max-age 指令出现在请求报文中,并且缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。 @@ -493,32 +512,13 @@ Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT ``` -## 连接管理 - -

- -### 1. 短连接与长连接 - -当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问 HTML 页面资源,还会请求图片资源。如果每进行一次 HTTP 通信就要新建一个 TCP 连接,那么开销会很大。 - -长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信。 - -- 从 HTTP/1.1 开始默认是长连接的,如果要断开连接,需要由客户端或者服务器端提出断开,使用 `Connection : close`; -- 在 HTTP/1.1 之前默认是短连接的,如果需要使用长连接,则使用 `Connection : Keep-Alive`。 - -### 2. 流水线 - -默认情况下,HTTP 请求是按顺序发出的,下一个请求只有在当前请求收到响应之后才会被发出。由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。 - -流水线是在同一条长连接上发出连续的请求,而不用等待响应返回,这样可以避免连接延迟。 - ## 内容协商 通过内容协商返回最合适的内容,例如根据浏览器的默认语言选择返回中文界面还是英文界面。 ### 1. 类型 -**(一)服务端驱动型** +**1.1 服务端驱动型** 客户端设置特定的 HTTP 首部字段,例如 Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Languag,服务器根据这些字段返回特定的资源。 @@ -528,7 +528,7 @@ If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT - 客户端提供的信息相当冗长(HTTP/2 协议的首部压缩机制缓解了这个问题),并且存在隐私风险(HTTP 指纹识别技术); - 给定的资源需要返回不同的展现形式,共享缓存的效率会降低,而服务器端的实现会越来越复杂。 -**(二)代理驱动型** +**1.2 代理驱动型** 服务器返回 300 Multiple Choices 或者 406 Not Acceptable,客户端从中选出最合适的那个资源。 @@ -758,7 +758,25 @@ HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见

-# 八、GET 和 POST 比较 +# 八、HTTP/1.1 新特性 + +详细内容请见上文 + +- 默认是长连接 + +- 支持管线化处理 + +- 支持同时打开多个 TCP 连接 + +- 支持虚拟主机 + +- 新增状态码 100 + +- 支持分块传输编码 + +- 新增缓存处理指令 max-age + +# 九、GET 和 POST 比较 ## 作用 @@ -840,23 +858,6 @@ DELETE /idX/delete HTTP/1.1 -> Returns 404 - 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有浏览器会这么做,例如火狐就不会。 - 而 GET 方法 Header 和 Data 会一起发送。 -# 九、HTTP/1.0 与 HTTP/1.1 的区别 - -详细内容请见上文 - -- HTTP/1.1 默认是长连接 - -- HTTP/1.1 支持管线化处理 - -- HTTP/1.1 支持同时打开多个 TCP 连接 - -- HTTP/1.1 支持虚拟主机 - -- HTTP/1.1 新增状态码 100 - -- HTTP/1.1 支持分块传输编码 - -- HTTP/1.1 新增缓存处理指令 max-age # 参考资料 From 02a61d361168f032deca5b960f066e4557d73784 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 24 Sep 2018 23:37:56 +0800 Subject: [PATCH 112/136] auto commit --- notes/Java 容器.md | 8 ++++---- notes/Leetcode 题解.md | 2 +- notes/剑指 offer 题解.md | 8 +++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index 3a7343f9..c039d6a8 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -100,7 +100,7 @@ List list = Arrays.asList(arr); 也可以使用以下方式调用 asList(): ```java -List list = Arrays.asList(1,2,3); +List list = Arrays.asList(1, 2, 3); ``` # 三、源码分析 @@ -575,7 +575,7 @@ int hash = hash(key); int i = indexFor(hash, table.length); ``` -(一)计算 hash 值 +**4.1 计算 hash 值** ```java final int hash(Object k) { @@ -600,7 +600,7 @@ public final int hashCode() { } ``` -(二)取模 +**4.2 取模** 令 x = 1<<4,即 x 为 2 的 4 次方,它具有以下性质: @@ -727,7 +727,7 @@ new capacity : 00100000 对于一个 Key, -- 它的哈希值如果在第 5 位上为 0,那么取模得到的结果和之前一样; +- 它的哈希值如果在第 6 位上为 0,那么取模得到的结果和之前一样; - 如果为 1,那么得到的结果为原来的结果 +16。 ### 7. 扩容-计算数组容量 diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 3e19a632..bdf03c8d 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2781,7 +2781,7 @@ return ret; 定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素。对于一个元素 x, - 如果它大于 tails 数组所有的值,那么把它添加到 tails 后面,表示最长递增子序列长度加 1; -- 如果 tails[i-1] < x <= tails[i],那么更新 tails[i-1] = x。 +- 如果 tails[i-1] < x <= tails[i],那么更新 tails[i] = x。 例如对于数组 [4,3,6,5],有: diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index e1a87b5b..6d06d767 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -223,14 +223,14 @@ Output: 在字符串尾部填充任意字符,使得字符串的长度等于替换之后的长度。因为一个空格要替换成三个字符(%20),因此当遍历到一个空格时,需要在尾部填充两个任意字符。 -令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。 +令 P1 指向字符串原来的末尾位置,P2 指向字符串现在的末尾位置。P1 和 P2 从后向前遍历,当 P1 遍历到一个空格时,就需要令 P2 指向的位置依次填充 02%(注意是逆序的),否则就填充上 P1 指向字符的值。 从后向前遍是为了在改变 P2 所指向的内容时,不会影响到 P1 遍历原来字符串的内容。 ```java public String replaceSpace(StringBuffer str) { int P1 = str.length() - 1; - for (int i = 0; i < P1 + 1; i++) + for (int i = 0; i <= P1; i++) if (str.charAt(i) == ' ') str.append(" "); @@ -385,6 +385,7 @@ private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int inL) { ```java public class TreeLinkNode { + int val; TreeLinkNode left = null; TreeLinkNode right = null; @@ -510,6 +511,7 @@ public int Fibonacci(int n) { ```java public class Solution { + private int[] fib = new int[40]; public Solution() { @@ -956,7 +958,7 @@ private void printNumber(char[] number) { ```java public ListNode deleteNode(ListNode head, ListNode tobeDelete) { - if (head == null || head.next == null || tobeDelete == null) + if (head == null || tobeDelete == null) return null; if (tobeDelete.next != null) { // 要删除的节点不是尾节点 From 1c861162ad6b9798e04cc3cd3a1421d6d1c6c93b Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 25 Sep 2018 01:02:18 +0800 Subject: [PATCH 113/136] auto commit --- notes/计算机网络.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/计算机网络.md b/notes/计算机网络.md index fba8a6d0..4328c5b7 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -155,7 +155,7 @@ TCP/IP 体系结构不严格遵循 OSI 分层概念,应用层可能会直接

-TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中占用举足轻重的地位。 +TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中占据举足轻重的地位。

@@ -320,7 +320,7 @@ MAC 地址是链路层地址,长度为 6 字节(48 位),用于唯一标 以太网是一种星型拓扑结构局域网。 -早期使用集线器进行连接,集线器是一种物理层设备, 作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到同时从两个不同接口的帧,那么就发生了碰撞。 +早期使用集线器进行连接,集线器是一种物理层设备, 作用于比特而不是帧,当一个比特到达接口时,集线器重新生成这个比特,并将其能量强度放大,从而扩大网络的传输距离,之后再将这个比特发送到其它所有接口。如果集线器同时收到两个不同接口的帧,那么就发生了碰撞。 目前以太网使用交换机替代了集线器,交换机是一种链路层设备,它不会发生碰撞,能根据 MAC 地址进行存储转发。 From 668ee4e846d82b2cc612b8e0044fc4d4ef10384d Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 25 Sep 2018 18:12:19 +0800 Subject: [PATCH 114/136] auto commit --- notes/计算机操作系统.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 00d26160..432aeca4 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性。而线程间可以通过直接读/写同一进程中的数据段(如全局变量)来进行通信(需要做好同步)。 +线程间可以通过直接读/写同一进程中的数据段来进行通信,但是进程通信需要借助 IPC。 ## 进程状态的切换 From 6d5190805c3620fa1f24cd21a1c60494241f4fa2 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 29 Sep 2018 22:34:48 +0800 Subject: [PATCH 115/136] auto commit --- notes/Java 并发.md | 2 +- notes/算法.md | 6 +++--- notes/设计模式.md | 11 +++++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/notes/Java 并发.md b/notes/Java 并发.md index add3982a..48d7463a 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -1280,7 +1280,7 @@ Thread 对象的结束先行发生于 join() 方法返回。 # 十一、线程安全 -多个线程不管以何种方式访问某个类,并在在主调代码中不需要进行同步,都能表现正确的行为。 +多个线程不管以何种方式访问某个类,并且1在主调代码中不需要进行同步,都能表现正确的行为。 线程安全有以下几种实现方式: diff --git a/notes/算法.md b/notes/算法.md index 1bc0690a..98e15931 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -694,7 +694,7 @@ private void swim(int k) { } ``` -类似地,当一个节点比子节点来得小,也需要不断地向下进行比较和交换操作,把这种操作称为下沉。一个节点如果有两个子节点,应当与两个子节点中最大那么节点进行交换。 +类似地,当一个节点比子节点来得小,也需要不断地向下进行比较和交换操作,把这种操作称为下沉。一个节点如果有两个子节点,应当与两个子节点中最大那个节点进行交换。

@@ -796,7 +796,7 @@ public class HeapSort> extends Sort { 对于堆排序,由于要对 N 个节点进行下沉操作,因此复杂度为 NlogN。 -堆排序时一种原地排序,没有利用额外的空间。 +堆排序是一种原地排序,没有利用额外的空间。 现代操作系统很少使用堆排序,因为它无法利用局部性原理进行缓存,也就是数组元素很少和相邻的元素进行比较。 @@ -1123,7 +1123,7 @@ public class ArrayStack implements MyStack { ### 2. 链表实现 -需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素时就可以通过 next 指针遍历到前一个压入栈的元素从而让这个元素称为新的栈顶元素。 +需要使用链表的头插法来实现,因为头插法中最后压入栈的元素在链表的开头,它的 next 指针指向前一个压入栈的元素,在弹出元素时就可以通过 next 指针遍历到前一个压入栈的元素从而让这个元素成为新的栈顶元素。 ```java public class ListStack implements MyStack { diff --git a/notes/设计模式.md b/notes/设计模式.md index f5029ec8..c4d74d10 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -143,7 +143,7 @@ if (uniqueInstance == null) { } ``` -uniqueInstance 采用 volatile 关键字修饰也是很有必要的。`uniqueInstance = new Singleton();` 这段代码其实是分为三步执行。 +uniqueInstance 采用 volatile 关键字修饰也是很有必要的, `uniqueInstance = new Singleton();` 这段代码其实是分为三步执行: 1. 为 uniqueInstance 分配内存空间 2. 初始化 uniqueInstance @@ -219,7 +219,14 @@ public enum Singleton { } ``` -该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现,为了保证不会出现反序列化之后出现多个实例,需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 +```html +firstName +secondName +secondName +secondName +``` + +该实现在多次序列化再进行反序列化之后,不会得到多个实例。而其它实现需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止多次实例化的代码。该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。 From af0cf63e24836dc28da3cdb3ecfa3aed6a48a0ec Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 29 Sep 2018 22:42:04 +0800 Subject: [PATCH 116/136] auto commit --- notes/设计模式.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/设计模式.md b/notes/设计模式.md index c4d74d10..b00cc84c 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -251,7 +251,7 @@ secondName ### Class Diagram -简单工厂不是设计模式,更像是一种编程习惯。它把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 +简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。 From abb0eca73d4d56cee77a4ab570aa2ad658d13699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=91=E6=B0=B8=E5=B7=9D?= <1029579233@qq.com> Date: Mon, 1 Oct 2018 19:29:54 +0800 Subject: [PATCH 117/136] Update Group.md --- other/Group.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/other/Group.md b/other/Group.md index e4d54b22..d56339d7 100644 --- a/other/Group.md +++ b/other/Group.md @@ -2,8 +2,6 @@ 这个交流群不是一个笔者的问题回答群,我更希望大家能够愿意积极回答,我相信提问和回答的过程都可以提高大家对知识的掌握程度。 -因为笔者白天要上班,因此不能及时进行回复,大部分时间会处于潜水状态。 - 至于交流群和 Issue 有什么区别,主要是两方面:一是交流群实时性高一些,二是交流群会更活跃一些。 另外,Issue 主要是用来发布一些项目中的错误和一些改进建议,当然也可以发布一些可以讨论的问题。 From 11831849f7b06301fb132c59c42aea1feced6ab0 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 1 Oct 2018 22:26:22 +0800 Subject: [PATCH 118/136] auto commit --- notes/Socket.md | 4 ++-- notes/计算机操作系统.md | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/notes/Socket.md b/notes/Socket.md index ddc47f56..c188580d 100644 --- a/notes/Socket.md +++ b/notes/Socket.md @@ -38,7 +38,7 @@ Unix 有五种 I/O 模型: 应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。 -应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。 +应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,所以不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。 下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。 @@ -62,7 +62,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * 它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。 -如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。并且相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。 +如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。

diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 432aeca4..7ed11bbe 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -173,7 +173,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅱ 调度 -线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。 +线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。 Ⅲ 系统开销 @@ -181,7 +181,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H Ⅳ 通信方面 -线程间可以通过直接读/写同一进程中的数据段来进行通信,但是进程通信需要借助 IPC。 +线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。 ## 进程状态的切换 @@ -243,7 +243,7 @@ QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 H **2.3 多级反馈队列** -如果一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。 +一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。 多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,..。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。 @@ -338,9 +338,9 @@ void consumer() { down(&full); down(&mutex); int item = remove_item(); + consume_item(item); up(&mutex); up(&empty); - consume_item(item); } } ``` @@ -837,7 +837,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。 -从上面的描述中可以看出,虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序称为可能。例如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0\~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。 +从上面的描述中可以看出,虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序成为可能。例如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0\~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。

@@ -989,7 +989,7 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问 优先调度与当前磁头所在磁道距离最近的磁道。 -虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。具体来说,两边的磁道请求更容易出现饥饿现象。 +虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。具体来说,两端的磁道请求更容易出现饥饿现象。

From a1debab6125f337747b7827ba04234232ab337d3 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 2 Oct 2018 16:29:31 +0800 Subject: [PATCH 119/136] auto commit --- notes/Java 基础.md | 6 +++--- notes/Java 并发.md | 2 +- notes/Redis.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/notes/Java 基础.md b/notes/Java 基础.md index a2cf6532..1cf3222a 100644 --- a/notes/Java 基础.md +++ b/notes/Java 基础.md @@ -284,7 +284,7 @@ public String(String original) { Java 的参数是以值传递的形式传入方法中,而不是引用传递。 -以下代码中 Dog dog 的 dog 是一个指针,存储的是对象的地址。在将一个参数传入一个方法时,本质上是将对象的地址以值的方式传递到形参中。因此在方法中改变指针引用的对象,那么这两个指针此时指向的是完全不同的对象,一方改变其所指向对象的内容对另一方没有影响。 +以下代码中 Dog dog 的 dog 是一个指针,存储的是对象的地址。在将一个参数传入一个方法时,本质上是将对象的地址以值的方式传递到形参中。因此在方法中使指针引用其它对象,那么这两个指针此时指向的是完全不同的对象,在一方改变其所指向对象的内容时对另一方没有影响。 ```java public class Dog { @@ -328,7 +328,7 @@ public class PassByValueExample { } ``` -但是如果在方法中改变对象的字段值会改变原对象该字段值,因为改变的是同一个地址指向的内容。 +如果在方法中改变对象的字段值会改变原对象该字段值,因为改变的是同一个地址指向的内容。 ```java class PassByValueExample { @@ -435,7 +435,7 @@ protected 用于修饰成员,表示在继承体系中成员对于子类可见 如果子类的方法重写了父类的方法,那么子类中该方法的访问级别不允许低于父类的访问级别。这是为了确保可以使用父类实例的地方都可以使用子类实例,也就是确保满足里氏替换原则。 -字段决不能是公有的,因为这么做的话就失去了对这个字段修改行为的控制,客户端可以对其随意修改。例如下面的例子中,AccessExample 拥有 id 共有字段,如果在某个时刻,我们想要使用 int 去存储 id 字段,那么就需要去修改所有的客户端代码。 +字段决不能是公有的,因为这么做的话就失去了对这个字段修改行为的控制,客户端可以对其随意修改。例如下面的例子中,AccessExample 拥有 id 公有字段,如果在某个时刻,我们想要使用 int 存储 id 字段,那么就需要修改所有的客户端代码。 ```java public class AccessExample { diff --git a/notes/Java 并发.md b/notes/Java 并发.md index 48d7463a..8b26ae91 100644 --- a/notes/Java 并发.md +++ b/notes/Java 并发.md @@ -1280,7 +1280,7 @@ Thread 对象的结束先行发生于 join() 方法返回。 # 十一、线程安全 -多个线程不管以何种方式访问某个类,并且1在主调代码中不需要进行同步,都能表现正确的行为。 +多个线程不管以何种方式访问某个类,并且在主调代码中不需要进行同步,都能表现正确的行为。 线程安全有以下几种实现方式: diff --git a/notes/Redis.md b/notes/Redis.md index fe34c7e7..e4653567 100644 --- a/notes/Redis.md +++ b/notes/Redis.md @@ -209,7 +209,7 @@ OK ## 字典 -dictht 是一个散列表结构,使用拉链法保存哈希冲突的 dictEntry。 +dictht 是一个散列表结构,使用拉链法保存哈希冲突。 ```c /* This is our hash table structure. Every dictionary has two of this as we @@ -253,7 +253,7 @@ rehash 操作不是一次性完成,而是采用渐进方式,这是为了避 在 rehash 期间,每次对字典执行添加、删除、查找或者更新操作时,都会执行一次渐进式 rehash。 -采用渐进式 rehash 会导致字典中的数据分散在两个 dictht 上,因此对字典的操作也需要到对应的 dictht 去执行。 +采用渐进式 rehash 会导致字典中的数据分散在两个 dictht 上,因此对字典的查找操作也需要到对应的 dictht 去执行。 ```c /* Performs N steps of incremental rehashing. Returns 1 if there are still From 74d4af6cedab284b27381ca29e00d17b274ef8a1 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 3 Oct 2018 20:49:02 +0800 Subject: [PATCH 120/136] auto commit --- notes/Leetcode 题解.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index bdf03c8d..1b89f548 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -103,7 +103,7 @@ Output: True Explanation: 1 * 1 + 2 * 2 = 5 ``` -题目描述:判断一个数是否为两个数的平方和,例如 5 = 12 + 22。 +题目描述:判断一个数是否为两个数的平方和。 ```java public boolean judgeSquareSum(int c) { @@ -130,7 +130,7 @@ public boolean judgeSquareSum(int c) { Given s = "leetcode", return "leotcede". ``` -使用双指针,指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。 +使用双指针指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。 ```java private final static HashSet vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')); @@ -307,6 +307,8 @@ private boolean isValid(String s, String target) { [215. Kth Largest Element in an Array (Medium)](https://leetcode.com/problems/kth-largest-element-in-an-array/description/) +题目描述:找到第 k 大的元素。 + **排序** :时间复杂度 O(NlogN),空间复杂度 O(1) ```java @@ -323,7 +325,7 @@ public int findKthLargest(int[] nums, int k) { PriorityQueue pq = new PriorityQueue<>(); // 小顶堆 for (int val : nums) { pq.add(val); - if (pq.size() > k) // 维护堆的大小为 K + if (pq.size() > k) // 维护堆的大小为 K pq.poll(); } return pq.peek(); @@ -555,7 +557,7 @@ Explanation: You don't need to remove any of the intervals since they're already 题目描述:计算让一组区间不重叠所需要移除的区间个数。 -计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 +先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 在每次选择中,区间的结尾最为重要,选择的区间结尾越小,留给后面的区间的空间越大,那么后面能够选择的区间个数也就越大。 @@ -639,7 +641,7 @@ Output: 题目描述:一个学生用两个分量 (h, k) 描述,h 表示身高,k 表示排在前面的有 k 个学生的身高比他高或者和他一样高。 -为了在每次插入操作时不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入第 k 个位置可能会变成第 k+1 个位置。 +为了使插入操作不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入的第 k 个位置可能会变成第 k+1 个位置。 身高降序、k 值升序,然后按排好序的顺序插入队列的第 k 个位置中。 @@ -825,7 +827,7 @@ public int binarySearch(int[] nums, int key) { **时间复杂度** -二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度都为 O(logN)。 +二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度为 O(logN)。 **m 计算** @@ -961,7 +963,7 @@ public char nextGreatestLetter(char[] letters, char target) { [540. Single Element in a Sorted Array (Medium)](https://leetcode.com/problems/single-element-in-a-sorted-array/description/) ```html -Input: [1,1,2,3,3,4,4,8,8] +Input: [1, 1, 2, 3, 3, 4, 4, 8, 8] Output: 2 ``` @@ -1132,11 +1134,11 @@ public List diffWaysToCompute(String input) {

-广度优先搜索的搜索过程有点像一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点。需要注意的是,遍历过的节点不能再次被遍历。 +广度优先搜索一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点。需要注意的是,遍历过的节点不能再次被遍历。 第一层: -- 0 -> {6,2,1,5}; +- 0 -> {6,2,1,5} 第二层: @@ -1150,7 +1152,7 @@ public List diffWaysToCompute(String input) { - 4 -> {} - 3 -> {} -可以看到,每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di<=dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。 +每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di <= dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。 在程序实现 BFS 时需要考虑以下问题: @@ -1180,19 +1182,17 @@ public int minPathLength(int[][] grids, int tr, int tc) { pathLength++; while (size-- > 0) { Pair cur = queue.poll(); + int cr = cur.getKey(), cc = cur.getValue(); + grids[cr][cc] = 0; // 标记 for (int[] d : direction) { - int nr = cur.getKey() + d[0], nc = cur.getValue() + d[1]; - Pair next = new Pair<>(nr, nc); - if (next.getKey() < 0 || next.getValue() >= m - || next.getKey() < 0 || next.getValue() >= n) { - + int nr = cr + d[0], nc = cc + d[1]; + if (nr < 0 || nr >= m || nc < 0 || nc >= n || grids[nr][nc] == 0) { continue; } - grids[next.getKey()][next.getValue()] = 0; // 标记 - if (next.getKey() == tr && next.getValue() == tc) { + if (nr == tr && nc == tc) { return pathLength; } - queue.add(next); + queue.add(new Pair<>(nr, nc)); } } } From 21f370ad2572e7c8eab7ddc1ec3e878f0a0fa163 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 3 Oct 2018 20:53:50 +0800 Subject: [PATCH 121/136] auto commit --- notes/Leetcode 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 1b89f548..11ae7b97 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -1239,7 +1239,7 @@ public int numSquares(int n) { continue; } marked[next] = true; - queue.add(cur - s); + queue.add(next); } } } From 237b54ee436a6a1350020e20e51425fc009d0b83 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 3 Oct 2018 20:57:01 +0800 Subject: [PATCH 122/136] auto commit --- notes/Leetcode 题解.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 11ae7b97..fb41a46d 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -1290,7 +1290,7 @@ Output: 0 Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. ``` -找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。 +题目描述:找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。 ```java public int ladderLength(String beginWord, String endWord, List wordList) { From a3f32a14d7b75c261db1b2e99a9b46a9f1c542be Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 4 Oct 2018 13:33:56 +0800 Subject: [PATCH 123/136] auto commit --- notes/Leetcode 题解.md | 57 +++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index bdf03c8d..bb6167c3 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -103,7 +103,7 @@ Output: True Explanation: 1 * 1 + 2 * 2 = 5 ``` -题目描述:判断一个数是否为两个数的平方和,例如 5 = 12 + 22。 +题目描述:判断一个数是否为两个数的平方和。 ```java public boolean judgeSquareSum(int c) { @@ -130,7 +130,7 @@ public boolean judgeSquareSum(int c) { Given s = "leetcode", return "leotcede". ``` -使用双指针,指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。 +使用双指针指向待反转的两个元音字符,一个指针从头向尾遍历,一个指针从尾到头遍历。 ```java private final static HashSet vowels = new HashSet<>(Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')); @@ -307,6 +307,8 @@ private boolean isValid(String s, String target) { [215. Kth Largest Element in an Array (Medium)](https://leetcode.com/problems/kth-largest-element-in-an-array/description/) +题目描述:找到第 k 大的元素。 + **排序** :时间复杂度 O(NlogN),空间复杂度 O(1) ```java @@ -323,7 +325,7 @@ public int findKthLargest(int[] nums, int k) { PriorityQueue pq = new PriorityQueue<>(); // 小顶堆 for (int val : nums) { pq.add(val); - if (pq.size() > k) // 维护堆的大小为 K + if (pq.size() > k) // 维护堆的大小为 K pq.poll(); } return pq.peek(); @@ -555,7 +557,7 @@ Explanation: You don't need to remove any of the intervals since they're already 题目描述:计算让一组区间不重叠所需要移除的区间个数。 -计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 +先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 在每次选择中,区间的结尾最为重要,选择的区间结尾越小,留给后面的区间的空间越大,那么后面能够选择的区间个数也就越大。 @@ -639,7 +641,7 @@ Output: 题目描述:一个学生用两个分量 (h, k) 描述,h 表示身高,k 表示排在前面的有 k 个学生的身高比他高或者和他一样高。 -为了在每次插入操作时不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入第 k 个位置可能会变成第 k+1 个位置。 +为了使插入操作不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入的第 k 个位置可能会变成第 k+1 个位置。 身高降序、k 值升序,然后按排好序的顺序插入队列的第 k 个位置中。 @@ -825,7 +827,7 @@ public int binarySearch(int[] nums, int key) { **时间复杂度** -二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度都为 O(logN)。 +二分查找也称为折半查找,每次都能将查找区间减半,这种折半特性的算法时间复杂度为 O(logN)。 **m 计算** @@ -961,7 +963,7 @@ public char nextGreatestLetter(char[] letters, char target) { [540. Single Element in a Sorted Array (Medium)](https://leetcode.com/problems/single-element-in-a-sorted-array/description/) ```html -Input: [1,1,2,3,3,4,4,8,8] +Input: [1, 1, 2, 3, 3, 4, 4, 8, 8] Output: 2 ``` @@ -1132,11 +1134,11 @@ public List diffWaysToCompute(String input) {

-广度优先搜索的搜索过程有点像一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点。需要注意的是,遍历过的节点不能再次被遍历。 +广度优先搜索一层一层地进行遍历,每层遍历都以上一层遍历的结果作为起点,遍历一个距离能访问到的所有节点。需要注意的是,遍历过的节点不能再次被遍历。 第一层: -- 0 -> {6,2,1,5}; +- 0 -> {6,2,1,5} 第二层: @@ -1150,7 +1152,7 @@ public List diffWaysToCompute(String input) { - 4 -> {} - 3 -> {} -可以看到,每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di<=dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。 +每一层遍历的节点都与根节点距离相同。设 di 表示第 i 个节点与根节点的距离,推导出一个结论:对于先遍历的节点 i 与后遍历的节点 j,有 di <= dj。利用这个结论,可以求解最短路径等 **最优解** 问题:第一次遍历到目的节点,其所经过的路径为最短路径。应该注意的是,使用 BFS 只能求解无权图的最短路径。 在程序实现 BFS 时需要考虑以下问题: @@ -1180,19 +1182,17 @@ public int minPathLength(int[][] grids, int tr, int tc) { pathLength++; while (size-- > 0) { Pair cur = queue.poll(); + int cr = cur.getKey(), cc = cur.getValue(); + grids[cr][cc] = 0; // 标记 for (int[] d : direction) { - int nr = cur.getKey() + d[0], nc = cur.getValue() + d[1]; - Pair next = new Pair<>(nr, nc); - if (next.getKey() < 0 || next.getValue() >= m - || next.getKey() < 0 || next.getValue() >= n) { - + int nr = cr + d[0], nc = cc + d[1]; + if (nr < 0 || nr >= m || nc < 0 || nc >= n || grids[nr][nc] == 0) { continue; } - grids[next.getKey()][next.getValue()] = 0; // 标记 - if (next.getKey() == tr && next.getValue() == tc) { + if (nr == tr && nc == tc) { return pathLength; } - queue.add(next); + queue.add(new Pair<>(nr, nc)); } } } @@ -1239,7 +1239,7 @@ public int numSquares(int n) { continue; } marked[next] = true; - queue.add(cur - s); + queue.add(next); } } } @@ -1290,7 +1290,7 @@ Output: 0 Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. ``` -找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。 +题目描述:找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。 ```java public int ladderLength(String beginWord, String endWord, List wordList) { @@ -1365,7 +1365,7 @@ private int getShortestPath(List[] graphic, int start, int end) { 广度优先搜索一层一层遍历,每一层得到的所有新节点,要用队列存储起来以备下一层遍历的时候再遍历。 -而深度优先搜索在得到一个新节点时立马对新节点进行遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4;如此反复以这种方式遍历新节点,直到没有新节点了,此时返回。返回到根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2,然后继续以上步骤。 +而深度优先搜索在得到一个新节点时立即对新节点进行遍历:从节点 0 出发开始遍历,得到到新节点 6 时,立马对新节点 6 进行遍历,得到新节点 4;如此反复以这种方式遍历新节点,直到没有新节点了,此时返回。返回到根节点 0 的情况是,继续对根节点 0 进行遍历,得到新节点 2,然后继续以上步骤。 从一个节点出发,使用 DFS 对一个图进行遍历时,能够遍历到的节点都是从初始节点可达的,DFS 常用来求解这种 **可达性** 问题。 @@ -1479,12 +1479,14 @@ Input: [[1,1,0], [1,1,0], [0,0,1]] + Output: 2 + Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. The 2nd student himself is in a friend circle. So return 2. ``` -好友关系可以看成是一个无向图,例如第 0 个人与第 1 个人是好友,那么 M[0][1] 和 M[1][0] 的值都为 1。 +题目描述:好友关系可以看成是一个无向图,例如第 0 个人与第 1 个人是好友,那么 M[0][1] 和 M[1][0] 的值都为 1。 ```java private int n; @@ -1530,7 +1532,7 @@ X X X X X O X X ``` -使被 'X' 包围的 'O' 转换为 'X'。 +题目描述:使被 'X' 包围的 'O' 转换为 'X'。 先填充最外侧,剩下的就是里侧了。 @@ -1678,7 +1680,6 @@ Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. ``` ```java - private static final String[] KEYS = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; public List letterCombinations(String digits) { @@ -2316,11 +2317,11 @@ private int cubeNum(int i, int j) { 一行一行地摆放,在确定一行中的那个皇后应该摆在哪一列时,需要用三个标记数组来确定某一列是否合法,这三个标记数组分别为:列标记数组、45 度对角线标记数组和 135 度对角线标记数组。 -45 度对角线标记数组的维度为 2 \* n - 1,通过下图可以明确 (r, c) 的位置所在的数组下标为 r + c。 +45 度对角线标记数组的长度为 2 \* n - 1,通过下图可以明确 (r, c) 的位置所在的数组下标为 r + c。

-135 度对角线标记数组的维度也是 2 \* n - 1,(r, c) 的位置所在的数组下标为 n - 1 - (r - c)。 +135 度对角线标记数组的长度也是 2 \* n - 1,(r, c) 的位置所在的数组下标为 n - 1 - (r - c)。

@@ -2414,9 +2415,9 @@ public int climbStairs(int n) { 定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。 -由于不能抢劫邻近住户,因此如果抢劫了第 i 个住户那么只能抢劫 i - 2 或者 i - 3 的住户,所以 +由于不能抢劫邻近住户,如果抢劫了第 i -1 个住户,那么就不能再抢劫第 i 个住户,所以 -

+

```java public int rob(int[] nums) { From 6eb176d506c924bf0ff5deea61f704c73a1d7583 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 4 Oct 2018 13:47:44 +0800 Subject: [PATCH 124/136] auto commit --- notes/Leetcode 题解.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index bb6167c3..960e3b1f 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -2538,7 +2538,7 @@ public int uniquePaths(int m, int n) { } ``` -也可以直接用数学公式求解,这是一个组合问题。机器人总共移动的次数 S=m+n-2,向下移动的次数 D=m-1,那么问题可以看成从 S 从取出 D 个位置的组合数量,这个问题的解为 C(S, D)。 +也可以直接用数学公式求解,这是一个组合问题。机器人总共移动的次数 S=m+n-2,向下移动的次数 D=m-1,那么问题可以看成从 S 中取出 D 个位置的组合数量,这个问题的解为 C(S, D)。 ```java public int uniquePaths(int m, int n) { @@ -2566,7 +2566,7 @@ sumRange(2, 5) -> -1 sumRange(0, 5) -> -3 ``` -求区间 i \~ j 的和,可以转换为 sum[j] - sum[i-1],其中 sum[i] 为 0 \~ i 的和。 +求区间 i \~ j 的和,可以转换为 sum[j + 1] - sum[i],其中 sum[i] 为 0 \~ i - 1 的和。 ```java class NumArray { From f7fd83baf4ed0693ff9597a812d51d444552a434 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 4 Oct 2018 13:54:39 +0800 Subject: [PATCH 125/136] auto commit --- notes/Leetcode 题解.md | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index 960e3b1f..dd435f37 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -804,6 +804,30 @@ public int maxProfit(int[] prices) { } ``` +**子数组最大的和** + +[53. Maximum Subarray (Easy)](https://leetcode.com/problems/maximum-subarray/description/) + +```html +For example, given the array [-2,1,-3,4,-1,2,1,-5,4], +the contiguous subarray [4,-1,2,1] has the largest sum = 6. +``` + +```java +public int maxSubArray(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int preSum = nums[0]; + int maxSum = preSum; + for (int i = 1; i < nums.length; i++) { + preSum = preSum > 0 ? preSum + nums[i] : nums[i]; + maxSum = Math.max(maxSum, preSum); + } + return maxSum; +} +``` + ## 二分查找 **正常实现** @@ -2586,30 +2610,6 @@ class NumArray { } ``` -**子数组最大的和** - -[53. Maximum Subarray (Easy)](https://leetcode.com/problems/maximum-subarray/description/) - -```html -For example, given the array [-2,1,-3,4,-1,2,1,-5,4], -the contiguous subarray [4,-1,2,1] has the largest sum = 6. -``` - -```java -public int maxSubArray(int[] nums) { - if (nums == null || nums.length == 0) { - return 0; - } - int preSum = nums[0]; - int maxSum = preSum; - for (int i = 1; i < nums.length; i++) { - preSum = preSum > 0 ? preSum + nums[i] : nums[i]; - maxSum = Math.max(maxSum, preSum); - } - return maxSum; -} -``` - **数组中等差递增子区间的个数** [413. Arithmetic Slices (Medium)](https://leetcode.com/problems/arithmetic-slices/description/) From 2a11c8f3969623da22a8dccbefaf12205f0ac99f Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 8 Oct 2018 11:47:50 +0800 Subject: [PATCH 126/136] auto commit --- notes/Leetcode 题解.md | 43 +++++++++--------- notes/Linux.md | 2 +- notes/计算机操作系统.md | 2 +- notes/设计模式.md | 2 +- pics/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png | Bin 0 -> 16384 bytes pics/f8b3f73d-0fda-449f-b55b-fa36b7ac04cd.png | Bin 0 -> 16384 bytes 6 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 pics/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png create mode 100644 pics/f8b3f73d-0fda-449f-b55b-fa36b7ac04cd.png diff --git a/notes/Leetcode 题解.md b/notes/Leetcode 题解.md index dd435f37..cfa4a59f 100644 --- a/notes/Leetcode 题解.md +++ b/notes/Leetcode 题解.md @@ -828,6 +828,28 @@ public int maxSubArray(int[] nums) { } ``` +**买入和售出股票最大的收益** + +[121. Best Time to Buy and Sell Stock (Easy)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/) + +题目描述:只进行一次交易。 + +只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。 + +```java +public int maxProfit(int[] prices) { + int n = prices.length; + if (n == 0) return 0; + int soFarMin = prices[0]; + int max = 0; + for (int i = 1; i < n; i++) { + if (soFarMin > prices[i]) soFarMin = prices[i]; + else max = Math.max(max, prices[i] - soFarMin); + } + return max; +} +``` + ## 二分查找 **正常实现** @@ -3340,27 +3362,6 @@ public int maxProfit(int[] prices, int fee) { } ``` -**买入和售出股票最大的收益** - -[121. Best Time to Buy and Sell Stock (Easy)](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/) - -题目描述:只进行一次交易。 - -只要记录前面的最小价格,将这个最小价格作为买入价格,然后将当前的价格作为售出价格,查看当前收益是不是最大收益。 - -```java -public int maxProfit(int[] prices) { - int n = prices.length; - if (n == 0) return 0; - int soFarMin = prices[0]; - int max = 0; - for (int i = 1; i < n; i++) { - if (soFarMin > prices[i]) soFarMin = prices[i]; - else max = Math.max(max, prices[i] - soFarMin); - } - return max; -} -``` **只能进行两次的股票交易** diff --git a/notes/Linux.md b/notes/Linux.md index 5e9528e6..a8ca85a3 100644 --- a/notes/Linux.md +++ b/notes/Linux.md @@ -1177,7 +1177,7 @@ dmtsai lines: 5 columns: 9 - 得到 SIGCHLD 信号; - waitpid() 或者 wait() 调用会返回。 -其中子进程发送的 SIGCHLD 信号包含了子进程的信息,包含了进程 ID、进程状态、进程使用 CPU 的时间等。 +其中子进程发送的 SIGCHLD 信号包含了子进程的信息,比如进程 ID、进程状态、进程使用 CPU 的时间等。 在子进程退出时,它的进程描述符不会立即释放,这是为了让父进程得到子进程信息,父进程通过 wait() 和 waitpid() 来获得一个已经退出的子进程的信息。 diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 7ed11bbe..3a30291c 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -719,7 +719,7 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 主要有以下四种方法: -- 鸵鸟策略; +- 鸵鸟策略 - 死锁检测与死锁恢复 - 死锁预防 - 死锁避免 diff --git a/notes/设计模式.md b/notes/设计模式.md index b00cc84c..6d779e2f 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -2352,7 +2352,7 @@ public class Client { ### Class Diagram -

+

### Implementation diff --git a/pics/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png b/pics/0889c0b4-07b4-45fc-873c-e0e16b97f67d.png new file mode 100644 index 0000000000000000000000000000000000000000..4d9e3e21c7e21a937fd22cd4ada140d5b9b95d64 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/pics/f8b3f73d-0fda-449f-b55b-fa36b7ac04cd.png b/pics/f8b3f73d-0fda-449f-b55b-fa36b7ac04cd.png new file mode 100644 index 0000000000000000000000000000000000000000..4d9e3e21c7e21a937fd22cd4ada140d5b9b95d64 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 From cd7860200a41c334624c67bbc3b7b70a3c13487e Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 9 Oct 2018 15:09:21 +0800 Subject: [PATCH 127/136] auto commit --- notes/数据库系统原理.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index 1ce774fa..b40557eb 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -55,7 +55,7 @@ 事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。 -回滚可以用日志来实现,日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。 +回滚可以用回滚日志来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。 ### 2. 一致性(Consistency) @@ -69,7 +69,7 @@ 一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。 -可以通过数据库备份和恢复来实现,在系统发生崩溃时,使用备份的数据库进行数据恢复。 +使用重做日志来保证持久性。 ---- From 3b8aa7e036a3569acc3d805935e2550894aa5b04 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 9 Oct 2018 15:20:40 +0800 Subject: [PATCH 128/136] auto commit --- notes/数据库系统原理.md | 3 ++- pics/12f958ee-ea02-481a-86ae-acc24934ad80.png | Bin 0 -> 27648 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 pics/12f958ee-ea02-481a-86ae-acc24934ad80.png diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index b40557eb..dfe1276c 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -80,7 +80,8 @@ - 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。 - 事务满足持久化是为了能应对数据库崩溃的情况。 -

+

+ ## AUTOCOMMIT diff --git a/pics/12f958ee-ea02-481a-86ae-acc24934ad80.png b/pics/12f958ee-ea02-481a-86ae-acc24934ad80.png new file mode 100644 index 0000000000000000000000000000000000000000..6d68340468e9f2150afd595d008de5fb1cfa1013 GIT binary patch literal 27648 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 B;UWM4 literal 0 HcmV?d00001 From be12581625e536468ab780ed3b63234d6b617164 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Tue, 9 Oct 2018 15:23:25 +0800 Subject: [PATCH 129/136] auto commit --- notes/数据库系统原理.md | 3 +-- pics/6675d713-8b59-4067-ad16-fdd538d4bb43.png | Bin 0 -> 30720 bytes 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 pics/6675d713-8b59-4067-ad16-fdd538d4bb43.png diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index dfe1276c..e4a8d514 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -80,8 +80,7 @@ - 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。 - 事务满足持久化是为了能应对数据库崩溃的情况。 -

- +

## AUTOCOMMIT diff --git a/pics/6675d713-8b59-4067-ad16-fdd538d4bb43.png b/pics/6675d713-8b59-4067-ad16-fdd538d4bb43.png new file mode 100644 index 0000000000000000000000000000000000000000..65048cb360dad4cb8c494be9e722bc2850fa92bf GIT binary patch literal 30720 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 fAS-^Z%{?|E+&ST>QWF4~ydeQFZt~l0Sid literal 0 HcmV?d00001 From fa0b976b8f215c898e103e95676ec21424d48606 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Wed, 10 Oct 2018 01:25:42 +0800 Subject: [PATCH 130/136] auto commit --- notes/分布式.md | 2 +- notes/数据库系统原理.md | 2 +- notes/系统设计基础.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/分布式.md b/notes/分布式.md index 2adba608..5af9c400 100644 --- a/notes/分布式.md +++ b/notes/分布式.md @@ -141,7 +141,7 @@ Zookeeper 提供了一种树形结构级的命名空间,/app1/p_1 节点的父 #### 2.2 单点问题 -协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其它操作。 +协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待,无法完成其它操作。 #### 2.3 数据不一致 diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md index e4a8d514..36e2a90d 100644 --- a/notes/数据库系统原理.md +++ b/notes/数据库系统原理.md @@ -80,7 +80,7 @@ - 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。 - 事务满足持久化是为了能应对数据库崩溃的情况。 -

+

## AUTOCOMMIT diff --git a/notes/系统设计基础.md b/notes/系统设计基础.md index ffa5de70..884bbe81 100644 --- a/notes/系统设计基础.md +++ b/notes/系统设计基础.md @@ -102,7 +102,7 @@ # 五、安全性 -要求系统的应对各种攻击手段时能够有可靠的应对措施。 +要求系统在应对各种攻击手段时能够有可靠的应对措施。 # 参考资料 From 37109f37c3bee1fa9b2b0dec96ef389892d2f4f0 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Thu, 11 Oct 2018 10:38:56 +0800 Subject: [PATCH 131/136] auto commit --- notes/Java 容器.md | 2 +- notes/计算机网络.md | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/notes/Java 容器.md b/notes/Java 容器.md index c039d6a8..c5a41bc0 100644 --- a/notes/Java 容器.md +++ b/notes/Java 容器.md @@ -730,7 +730,7 @@ new capacity : 00100000 - 它的哈希值如果在第 6 位上为 0,那么取模得到的结果和之前一样; - 如果为 1,那么得到的结果为原来的结果 +16。 -### 7. 扩容-计算数组容量 +### 7. 计算数组容量 HashMap 构造函数允许用户传入的容量不是 2 的 n 次方,因为它可以自动地将传入的容量转换为 2 的 n 次方。 diff --git a/notes/计算机网络.md b/notes/计算机网络.md index 4328c5b7..301effcf 100644 --- a/notes/计算机网络.md +++ b/notes/计算机网络.md @@ -31,7 +31,7 @@ * [路由器的结构](#路由器的结构) * [路由器分组转发流程](#路由器分组转发流程) * [路由选择协议](#路由选择协议) -* [五、运输层](#五运输层) +* [五、传输层](#五传输层) * [UDP 和 TCP 的特点](#udp-和-tcp-的特点) * [UDP 首部格式](#udp-首部格式) * [TCP 首部格式](#tcp-首部格式) @@ -129,9 +129,9 @@ - **应用层** :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等。数据单位为报文。 -- **运输层** :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的运输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 +- **传输层** :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。 -- **网络层** :为主机提供数据传输服务。而运输层协议是为主机中的进程提供数据传输服务。网络层把运输层传递下来的报文段或者用户数据报封装成分组。 +- **网络层** :为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。 - **数据链路层** :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。 @@ -163,7 +163,7 @@ TCP/IP 协议族是一种沙漏形状,中间小两边大,IP 协议在其中 在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部。 -路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要运输层和应用层。 +路由器只有下面三层协议,因为路由器位于网络核心中,不需要为进程或者应用程序提供服务,因此也就不需要传输层和应用层。

@@ -498,7 +498,7 @@ VPN 使用公用的互联网作为本机构各专用网之间的通信载体。 专用网内部的主机使用本地 IP 地址又想和互联网上的主机通信时,可以使用 NAT 来将本地 IP 转换为全球 IP。 -在以前,NAT 将本地 IP 和全球 IP 一一对应,这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网。为了更有效地利用全球 IP 地址,现在常用的 NAT 转换表把运输层的端口号也用上了,使得多个专用网内部的主机共用一个全球 IP 地址。使用端口号的 NAT 也叫做网络地址与端口转换 NAPT。 +在以前,NAT 将本地 IP 和全球 IP 一一对应,这种方式下拥有 n 个全球 IP 地址的专用网内最多只可以同时有 n 台主机接入互联网。为了更有效地利用全球 IP 地址,现在常用的 NAT 转换表把传输层的端口号也用上了,使得多个专用网内部的主机共用一个全球 IP 地址。使用端口号的 NAT 也叫做网络地址与端口转换 NAPT。

@@ -578,9 +578,9 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。

-# 五、运输层 +# 五、传输层 -网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。运输层提供了进程间的逻辑通信,运输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个运输层实体之间有一条端到端的逻辑通信信道。 +网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信,传输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个传输层实体之间有一条端到端的逻辑通信信道。 ## UDP 和 TCP 的特点 @@ -808,7 +808,7 @@ IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删 ## 常用端口 -|应用| 应用层协议 | 端口号 | 运输层协议 | 备注 | +|应用| 应用层协议 | 端口号 | 传输层协议 | 备注 | | :---: | :--: | :--: | :--: | :--: | 域名解析 | DNS | 53 | UDP/TCP | 长度超过 512 字节时使用 TCP | | 动态主机配置协议 | DHCP | 67/68 | UDP | | From c2eb9422b8eb5d57034943e4dbe4ef23eb63a6d4 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 12 Oct 2018 14:13:01 +0800 Subject: [PATCH 132/136] auto commit --- notes/HTTP.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index f9abd238..56f7e5f9 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -378,7 +378,7 @@ Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径 ### 5. JavaScript -通过 `Document.cookie` 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie。 +通过 `document.cookie` 属性可创建新的 Cookie,也可通过该属性访问非 HttpOnly 标记的 Cookie。 ```html document.cookie = "yummy_cookie=choco"; @@ -388,7 +388,7 @@ console.log(document.cookie); ### 6. HttpOnly -标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 +标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。 ```html Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly @@ -520,7 +520,7 @@ If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT **1.1 服务端驱动型** -客户端设置特定的 HTTP 首部字段,例如 Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Languag,服务器根据这些字段返回特定的资源。 +客户端设置特定的 HTTP 首部字段,例如 Accept、Accept-Charset、Accept-Encoding、Accept-Language,服务器根据这些字段返回特定的资源。 它存在以下问题: From 73d782bb2a14ca1be347dc45110b30bbd27d55eb Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Fri, 12 Oct 2018 20:55:43 +0800 Subject: [PATCH 133/136] auto commit --- notes/Java 虚拟机.md | 2 +- notes/剑指 offer 题解.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/notes/Java 虚拟机.md b/notes/Java 虚拟机.md index 2ad1527c..2dafe334 100644 --- a/notes/Java 虚拟机.md +++ b/notes/Java 虚拟机.md @@ -169,7 +169,7 @@ finalize() 类似 C++ 的析构函数,用来做关闭外部资源等工作。 ## 引用类型 -无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象是否可达,判定对象是否可被回收都与引用有关。 +无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是否可达,判定对象是否可被回收都与引用有关。 Java 提供了四种强度不同的引用类型。 diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index 6d06d767..54ed6cd2 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -2690,8 +2690,8 @@ public ArrayList maxInWindows(int[] num, int size) { for (int i = 0; i < size; i++) heap.add(num[i]); ret.add(heap.peek()); - for (int i = 1, j = i + size - 1; j < num.length; i++, j++) { /* 维护一个大小为 size 的大顶堆 */ - heap.remove(num[i - 1]); + for (int i = 0, j = i + size; j < num.length; i++, j++) { /* 维护一个大小为 size 的大顶堆 */ + heap.remove(num[i]); heap.add(num[j]); ret.add(heap.peek()); } From 514a4b33dd43be1128291f1c3228c0d086d0060f Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sat, 13 Oct 2018 21:38:28 +0800 Subject: [PATCH 134/136] auto commit --- notes/算法.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes/算法.md b/notes/算法.md index 98e15931..d6e21d6a 100644 --- a/notes/算法.md +++ b/notes/算法.md @@ -301,7 +301,7 @@ public class Selection> extends Sort { @Override public void sort(T[] nums) { int N = nums.length; - for (int i = 0; i < N; i++) { + for (int i = 0; i < N - 1; i++) { int min = i; for (int j = i + 1; j < N; j++) { if (less(nums[j], nums[min])) { From d0d5048f7bd961889f5ad04e1c7665df887de61c Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Sun, 14 Oct 2018 16:33:10 +0800 Subject: [PATCH 135/136] auto commit --- notes/计算机操作系统.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/计算机操作系统.md b/notes/计算机操作系统.md index 3a30291c..8ae04fd2 100644 --- a/notes/计算机操作系统.md +++ b/notes/计算机操作系统.md @@ -845,9 +845,9 @@ FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户 内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表(Page table)存储着页(程序地址空间)和页框(物理内存空间)的映射表。 -下图的页表存放着 16 个页,这 16 个页需要用 4 个比特位来进行索引定位,也就是存储页面号,剩下 12 个比特位存储偏移量。 +一个虚拟地址分成两个部分,一部分存储页面号,一部分存储偏移量。 -例如对于虚拟地址(0010 000000000100),前 4 位是存储页面号 2,读取表项内容为(110 1)。该页在内存中,并且页框的地址为 (110 000000000100)。 +下图的页表存放着 16 个页,这 16 个页需要用 4 个比特位来进行索引定位。例如对于虚拟地址(0010 000000000100),前 4 位是存储页面号 2,读取表项内容为(110 1),页表项最后一位表示是否存在于内存中,1 表示存在。后 12 位存储偏移量。这个页对应的页框的地址为 (110 000000000100)。

From 89ff7a1ad25b62b21dc88aead40ff807a74475b5 Mon Sep 17 00:00:00 2001 From: CyC2018 <1029579233@qq.com> Date: Mon, 15 Oct 2018 21:51:19 +0800 Subject: [PATCH 136/136] auto commit --- notes/HTTP.md | 2 +- notes/MySQL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/notes/HTTP.md b/notes/HTTP.md index 56f7e5f9..ffe01382 100644 --- a/notes/HTTP.md +++ b/notes/HTTP.md @@ -764,7 +764,7 @@ HTTP/2.0 要求客户端和服务器同时维护和更新一个包含之前见 - 默认是长连接 -- 支持管线化处理 +- 支持流水线 - 支持同时打开多个 TCP 连接 diff --git a/notes/MySQL.md b/notes/MySQL.md index f5479685..bb02df8b 100644 --- a/notes/MySQL.md +++ b/notes/MySQL.md @@ -220,7 +220,7 @@ Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explai 一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。 ```sql -DELEFT FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); +DELETE FROM messages WHERE create < DATE_SUB(NOW(), INTERVAL 3 MONTH); ``` ```sql