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 001/139] 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 002/139] 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 003/139] 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 004/139] 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 005/139] 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 006/139] 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 007/139] 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 008/139] 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 009/139] 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 010/139] 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 011/139] 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 012/139] 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 013/139] =?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题吧~
+
+
\ 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 014/139] 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题吧~
-
-
\ 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 015/139] 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 016/139] =?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 017/139] 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 018/139] =?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 019/139] =?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 020/139] =?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 021/139] 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 022/139] 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 023/139] 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 024/139] =?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 025/139] 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 026/139] 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 027/139] 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 028/139] 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 029/139] =?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 030/139] 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 031/139] =?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 032/139] 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 033/139] 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 034/139] =?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 035/139] 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 036/139] =?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 037/139] =?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 038/139] =?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 039/139] =?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 040/139] =?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 041/139] 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 042/139] 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 043/139] 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 044/139] =?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 045/139] 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 046/139] 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 047/139] 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 048/139] 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 049/139] 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 050/139] 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 的住户,所以
-
-+nums[i])
+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 051/139] 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 052/139] =?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 053/139] 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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