8000 Merge branch 'master' of github.com:hollischuang/toBeTopJavaer · amgm-coder/toBeTopJavaer@2698d4a · GitHub
[go: up one dir, main page]

Skip to content

Commit 2698d4a

Browse files
author
hollis.zhl
committed
Merge branch 'master' of github.com:hollischuang/toBeTopJavaer
2 parents da04e0d + 48da67f commit 2698d4a

File tree

8 files changed

+25
-25
lines changed

8 files changed

+25
-25
lines changed

docs/basics/java-basic/bio-vs-nio-vs-aio.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
### IO
2-
什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。
2+
什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。
33

44
在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。
55

@@ -25,7 +25,7 @@ Java AIO即Async非阻塞,是异步非阻塞的IO。
2525

2626
BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。
2727

28-
NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。
28+
NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断地轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。
2929

3030
AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。
3131

@@ -225,4 +225,4 @@ public class WriteToFile {
225225
226226
}
227227
}
228-
```
228+
```

docs/basics/java-basic/enum-impl.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ Java SE5提供了一种新的类型-Java的枚举类型,关键字enum可以将
4040
}
4141
}
4242

43-
通过反编译后代码我们可以看到,public final class T extends Enum,说明,该类是继承了Enum类的,同时final关键字告诉我们,这个类也是不能被继承的。
43+
通过反编译代码我们可以看到,public final class T extends Enum,说明,该类是继承了Enum类的,同时final关键字告诉我们,这个类也是不能被继承的。
4444

45-
当我们使用enmu来定义一个枚举类型的时候,编译器会自动帮我们创建一个final类型的类继承Enum类,所以枚举类型不能被继承。
45+
当我们使用enmu来定义一个枚举类型的时候,编译器会自动帮我们创建一个final类型的类继承Enum类,所以枚举类型不能被继承。

docs/basics/java-basic/enum-serializable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191

9292
**2\. 枚举自己处理序列化**
9393

94-
> 我们知道,以前的所有的单例模式都有一个比较大的问题,就是一旦实现了Serializable接口之后,就不再是单例得了,因为,每次调用 readObject()方法返回的都是一个新创建出来的对象,有一种解决办法就是使用readResolve()方法来避免此事发生。但是,**为了保证枚举类型像Java规范中所说的那样,每一个枚举类型极其定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定。**原文如下:
94+
> 我们知道,以前的所有的单例模式都有一个比较大的问题,就是一旦实现了Serializable接口之后,就不再是单例的了,因为,每次调用 readObject()方法返回的都是一个新创建出来的对象,有一种解决办法就是使用readResolve()方法来避免此事发生。但是,**为了保证枚举类型像Java规范中所说的那样,每一个枚举类型及其定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定。**原文如下:
9595
>
9696
> > Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream. The process by which enum constants are serialized cannot be customized: any class-specific writeObject, readObject, readObjectNoData, writeReplace, and readResolve methods defined by enum types are ignored during serialization and deserialization. Similarly, any serialPersistentFields or serialVersionUID field declarations are also ignored--all enum types have a fixedserialVersionUID of 0L. Documenting serializable fields and data for enum types is unnecessary, since there is no variation in the type of data sent.
9797
>

docs/basics/java-basic/enum-singleton.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
单例相关文章一览:
44

5-
[设计模式(二)——单例模式][1]
6-
[设计模式(三)——JDK中的那些单例][2]
7-
[单例模式的七种写法][3]
8-
[单例与序列化的那些事儿][4]
9-
[不使用synchronized和lock,如何实现一个线程安全的单例?][5]
10-
[不使用synchronized和lock,如何实现一个线程安全的单例?(二)][6]
5+
[设计模式(二)——单例模式][1]
6+
[设计模式(三)——JDK中的那些单例][2]
7+
[单例模式的七种写法][3]
8+
[单例与序列化的那些事儿][4]
9+
[不使用synchronized和lock,如何实现一个线程安全的单例?][5]
10+
[不使用synchronized和lock,如何实现一个线程安全的单例?(二)][6]
1111

1212
如果你对单例不是很了解,或者对于单例的线程安全问题以及序列化会破坏单例等问题不是很清楚,可以先阅读以上文章。上面六篇文章看完之后,相信你一定会对单例模式有更多,更深入的理解。
1313

1414
我们知道,单例模式,一般有七种写法,那么这七种写法中,最好的是哪一种呢?为什么呢?本文就来抽丝剥茧一下。
1515

1616
### 哪种写单例的方式最好
1717

18-
在StakcOverflow中,有一个关于[What is an efficient way to implement a singleton pattern in Java?][7]的讨论:
18+
在StackOverflow中,有一个关于[What is an efficient way to implement a singleton pattern in Java?][7]的讨论:
1919

2020
<img src="https://www.hollischuang.com/wp-content/uploads/2018/06/enum.png" alt="" width="1500" height="1158" class="aligncenter size-full wp-image-3683" />
2121

@@ -78,7 +78,7 @@
7878

7979
通过将定义好的枚举[反编译][9],我们就能发现,其实枚举在经过`javac`的编译之后,会被转换成形如`public final class T extends Enum`的定义。
8080

81-
而且,枚举中的各个枚举项同事通过`static`来定义的。如:
81+
而且,枚举中的各个枚举项同时通过`static`来定义的。如:
8282

8383
public enum T {
8484
SPRING,SUMMER,AUTUMN,WINTER;
@@ -145,4 +145,4 @@
145145
[9]: http://www.hollischuang.com/archives/58
146146
[10]: http://www.hollischuang.com/archives/199
147147
[11]: http://www.hollischuang.com/archives/201
148-
[12]: https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html#6469
148+
[12]: https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html#6469

docs/basics/java-basic/enum-usage.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
}
4343

4444

45-
程序`getChineseSeason(Season.SPRING)`是我们预期的使用方法。可`getChineseSeason(5)`显然就不是了,而且编译很通过,在运行时会出现什么情况,我们就不得而知了。这显然就不符合`Java`程序的类型安全。
45+
程序`getChineseSeason(Season.SPRING)`是我们预期的使用方法。可`getChineseSeason(5)`显然就不是了,而且编译会通过,在运行时会出现什么情况,我们就不得而知了。这显然就不符合`Java`程序的类型安全。
4646

47-
接下来我们来考虑一下这种模式的**可读性**。使用枚举的大多数场合,我都需要方便得到枚举类型的字符串表达式。如果将`int`枚举常量打印出来,我们所见到的就是一组数字,这是没什么太大的用处。我们可能会想到使用`String`常量代替`int`常量。虽然它为这些常量提供了可打印的字符串,但是它会导致性能问题,因为它依赖于字符串的比较操作,所以这种模式也是我们不期望的。 从**类型安全性****程序可读性**两方面考虑,`int``String`枚举模式的缺点就显露出来了。幸运的是,从`Java1.5`发行版本开始,就提出了另一种可以替代的解决方案,可以避免`int``String`枚举模式的缺点,并提供了许多额外的好处。那就是枚举类型(`enum type`)。接下来的章节将介绍枚举类型的定义、特征、应用场景和优缺点。
47+
接下来我们来考虑一下这种模式的**可读性**。使用枚举的大多数场合,我都需要方便得到枚举类型的字符串表达式。如果将`int`枚举常量打印出来,我们所见到的就是一组数字,这没什么太大的用处。我们可能会想到使用`String`常量代替`int`常量。虽然它为这些常量提供了可打印的字符串,但是它会导致性能问题,因为它依赖于字符串的比较操作,所以这种模式也是我们不期望的。 从**类型安全性****程序可读性**两方面考虑,`int``String`枚举模式的缺点就显露出来了。幸运的是,从`Java1.5`发行版本开始,就提出了另一种可以替代的解决方案,可以避免`int``String`枚举模式的缺点,并提供了许多额外的好处。那就是枚举类型(`enum type`)。接下来的章节将介绍枚举类型的定义、特征、应用场景和优缺点。
4848

4949
### 2 定义
5050

docs/basics/java-basic/fail-fast-vs-fail-safe.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ CMException,当方法检测到对象的并发修改,但不允许这种修改
111111
}
112112

113113

114-
如上,在该方法中对modCount和expectedModCount进行了比较,如果二者不想等,则抛出CMException。
114+
如上,在该方法中对modCount和expectedModCount进行了比较,如果二者不相等,则抛出CMException。
115115

116-
那么,modCount和expectedModCount是什么?是什么原因导致他们的值不想等的呢
116+
那么,modCount和expectedModCount是什么?是什么原因导致他们的值不相等的呢
117117

118118
modCount是ArrayList中的一个成员变量。它表示该集合实际被修改的次数。
119119

docs/basics/java-basic/linux-io.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ while(true){
4949

5050
而多路复用IO模式,通过一个线程就可以管理多个socket,只有当socket真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用IO比较适合连接数比较多的情况。
5151

52-
另外多路复用IO为何比非阻塞IO模型的效率高是因为在非阻塞IO中,不断地询问socket状态时通过用户线程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。
52+
另外多路复用IO为何比非阻塞IO模型的效率高是因为在非阻塞IO中,不断地询问socket状态是通过用户线程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。
5353

5454

5555
不过要注意的是,多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。
@@ -60,10 +60,10 @@ while(true){
6060
在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。
6161

6262
### 异步IO模型
63-
异步IO模型是比较理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。
63+
异步IO模型是比较理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要知道实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。
6464

65-
也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作
65+
也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用IO函数进行实际的读写操作
6666

6767
注意,异步IO是需要操作系统的底层支持,在Java 7中,提供了Asynchronous IO。
6868

69-
前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。
69+
前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

docs/basics/java-basic/synchronized-vs-asynchronization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
3 老张把响水壶放到火上,一直在水壶旁等着水开。(异步阻塞)
2121
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
2222

23-
1和2的区别是,调用方在得到返回之前所做的事情不一行
24-
1和3的区别是,被调用方对于烧水的处理不一样。
23+
1和2的区别是,调用方在得到返回之前所做的事情不一样
24+
1和3的区别是,被调用方对于烧水的处理不一样。

0 commit comments

Comments
 (0)
0