auto commit
This commit is contained in:
parent
0867a68e27
commit
46f19d913c
|
@ -6,7 +6,7 @@
|
|||
* [装饰者模式](#装饰者模式)
|
||||
* [四、字符操作](#四字符操作)
|
||||
* [编码与解码](#编码与解码)
|
||||
* [String](#string)
|
||||
* [String 的编码方式](#string-的编码方式)
|
||||
* [Reader 与 Writer](#reader-与-writer)
|
||||
* [实现逐行输出文本文件的内容](#实现逐行输出文本文件的内容)
|
||||
* [五、对象操作](#五对象操作)
|
||||
|
@ -121,7 +121,7 @@ UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-
|
|||
|
||||
Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
|
||||
|
||||
## String
|
||||
## String 的编码方式
|
||||
|
||||
String 可以看成一个字符序列,可以指定一个编码方式将它编码为字节序列,也可以指定一个编码方式将一个字节序列解码为 String。
|
||||
|
||||
|
@ -371,7 +371,7 @@ public static void fastCopy(String src, String dist) throws IOException {
|
|||
/* 获取目标文件的输出字节流 */
|
||||
FileOutputStream fout = new FileOutputStream(dist);
|
||||
|
||||
/* 获取输出字节流的通道 */
|
||||
/* 获取输出字节流的文件通道 */
|
||||
FileChannel fcout = fout.getChannel();
|
||||
|
||||
/* 为缓冲区分配 1024 个字节 */
|
||||
|
@ -407,7 +407,7 @@ NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用
|
|||
|
||||
通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。
|
||||
|
||||
因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件具有更好的性能。
|
||||
因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件,对于 IO 密集型的应用具有很好地性能。
|
||||
|
||||
应该注意的是,只有套接字 Channel 才能配置为非阻塞,而 FileChannel 不能,为 FileChannel 配置非阻塞也没有意义。
|
||||
|
||||
|
@ -601,8 +601,8 @@ MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
|
|||
|
||||
NIO 与普通 I/O 的区别主要有以下两点:
|
||||
|
||||
- NIO 是非阻塞的
|
||||
- NIO 面向块,I/O 面向流
|
||||
- NIO 是非阻塞的;
|
||||
- NIO 面向块,I/O 面向流。
|
||||
|
||||
# 八、参考资料
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现,它具
|
|||
|
||||
进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。
|
||||
|
||||
插入删除操作记录会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。
|
||||
插入删除操作会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。
|
||||
|
||||
### 3. 与红黑树的比较
|
||||
|
||||
|
@ -233,7 +233,7 @@ do {
|
|||
|
||||
### 2. 分解大连接查询
|
||||
|
||||
将一个大连接查询分解成对每一个表进行一次单表查询,然后将结果在应用程序中进行关联,这样做的好处有:
|
||||
将一个大连接查询分解成对每一个表进行一次单表查询,然后在应用程序中进行关联,这样做的好处有:
|
||||
|
||||
- 让缓存更高效。对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。
|
||||
- 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。
|
||||
|
@ -332,7 +332,7 @@ MySQL 提供了两种相似的日期时间类型:DATETIME 和 TIMESTAMP。
|
|||
|
||||
### 2. TIMESTAMP
|
||||
|
||||
和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。
|
||||
和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年到 2038 年。
|
||||
|
||||
它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。
|
||||
|
||||
|
@ -372,9 +372,9 @@ MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提
|
|||
|
||||
使用分布式事务来解决,比如 XA 接口。
|
||||
|
||||
### 2. 链接
|
||||
### 2. JOIN
|
||||
|
||||
可以将原来的 JOIN 分解成多个单表查询,然后在用户程序中进行 JOIN。
|
||||
可以将原来的 JOIN 分解成多个单表 JOIN 查询,然后在用户程序中进行 JOIN。
|
||||
|
||||
### 3. ID 唯一性
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。
|
||||
|
||||
键的类型只能为字符串,值支持的五种类型数据类型为:字符串、列表、集合、散列表、有序集合。
|
||||
键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。
|
||||
|
||||
Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。
|
||||
|
||||
|
@ -58,7 +58,7 @@ Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,
|
|||
| 数据类型 | 可以存储的值 | 操作 |
|
||||
| :--: | :--: | :--: |
|
||||
| STRING | 字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作</br> 对整数和浮点数执行自增或者自减操作 |
|
||||
| LIST | 列表 | 从两端压入或者弹出元素</br> 对单个或者多个元素</br> 进行修剪,只保留一个范围内的元素 |
|
||||
| LIST | 列表 | 从两端压入或者弹出元素 </br> 对单个或者多个元素</br> 进行修剪,只保留一个范围内的元素 |
|
||||
| SET | 无序集合 | 添加、获取、移除单个元素</br> 检查一个元素是否存在于集合中</br> 计算交集、并集、差集</br> 从集合里面随机获取元素 |
|
||||
| HASH | 包含键值对的无序散列表 | 添加、获取、移除单个键值对</br> 获取所有键值对</br> 检查某个键是否存在|
|
||||
| ZSET | 有序集合 | 添加、获取、删除元素</br> 根据分值范围或者成员来获取元素</br> 计算一个键的排名 |
|
||||
|
@ -357,7 +357,7 @@ List 是一个双向链表,可以通过 lpop 和 lpush 写入和读取消息
|
|||
|
||||
在分布式场景下具有多个应用服务器,可以使用 Redis 来统一存储这些应用服务器的会话信息。
|
||||
|
||||
当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器。
|
||||
当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
|
||||
|
||||
## 分布式锁实现
|
||||
|
||||
|
@ -393,7 +393,7 @@ Redis Cluster 实现了分布式的支持。
|
|||
|
||||
- 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘,而 Memcached 的数据则会一直在内存中。
|
||||
|
||||
- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题,但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。
|
||||
- Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。
|
||||
|
||||
# 六、键的过期时间
|
||||
|
||||
|
@ -605,5 +605,4 @@ Redis 没有关系型数据库中的表这一概念来将同种类型的数据
|
|||
- [论述 Redis 和 Memcached 的差异](http://www.cnblogs.com/loveincode/p/7411911.html)
|
||||
- [Redis 3.0 中文版- 分片](http://wiki.jikexueyuan.com/project/redis-guide)
|
||||
- [Redis 应用场景](http://www.scienjus.com/redis-use-case/)
|
||||
- [Observer vs Pub-Sub](http://developers-club.com/posts/270339/)
|
||||
- [Using Redis as an LRU cache](https://redis.io/topics/lru-cache)
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
- 等待数据准备好
|
||||
- 从内核向进程复制数据
|
||||
|
||||
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
|
||||
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待数据到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。
|
||||
|
||||
Unix 下有五种 I/O 模型:
|
||||
Unix 有五种 I/O 模型:
|
||||
|
||||
- 阻塞式 I/O
|
||||
- 非阻塞式 I/O
|
||||
|
@ -39,7 +39,7 @@ Unix 下有五种 I/O 模型:
|
|||
|
||||
应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。
|
||||
|
||||
应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的执行效率会比较高。
|
||||
应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的 CPU 利用率效率会比较高。
|
||||
|
||||
下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。
|
||||
|
||||
|
@ -53,13 +53,13 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
|||
|
||||
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。
|
||||
|
||||
由于 CPU 要处理更多的系统调用,因此这种模型是比较低效的。
|
||||
由于 CPU 要处理更多的系统调用,因此这种模型的 CPU 利用率是比较低的。
|
||||
|
||||
<div align="center"> <img src="../pics//1492929000361_5.png"/> </div><br>
|
||||
|
||||
## I/O 复用
|
||||
|
||||
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读,这一过程会被阻塞,当某一个套接字可读时返回。之后再使用 recvfrom 把数据从内核复制到进程中。
|
||||
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读。这一过程会被阻塞,当某一个套接字可读时返回,之后再使用 recvfrom 把数据从内核复制到进程中。
|
||||
|
||||
它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。
|
||||
|
||||
|
@ -77,7 +77,7 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
|
|||
|
||||
## 异步 I/O
|
||||
|
||||
进行 aio_read 系统调用会立即返回,应用进程继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
|
||||
应用进程执行 aio_read 系统调用会立即返回,应用进程可以继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。
|
||||
|
||||
异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O。
|
||||
|
||||
|
@ -198,7 +198,7 @@ else
|
|||
select 和 poll 的功能基本相同,不过在一些实现细节上有所不同。
|
||||
|
||||
- select 会修改描述符,而 poll 不会;
|
||||
- select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用链表实现,没有描述符的数量的限制;
|
||||
- select 的描述符类型使用数组实现,FD_SETSIZE 大小默认为 1024,因此默认只能监听 1024 个描述符。如果要监听更多描述符的话,需要修改 FD_SETSIZE 之后重新编译;而 poll 的描述符类型使用链表实现,没有描述符数量的限制;
|
||||
- poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高。
|
||||
- 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定。
|
||||
|
||||
|
|
|
@ -230,9 +230,9 @@ Output:
|
|||
```java
|
||||
public String replaceSpace(StringBuffer str) {
|
||||
int P1 = str.length() - 1;
|
||||
for (int i = 0; i < P1+1; i++)
|
||||
for (int i = 0; i < P1 + 1; i++)
|
||||
if (str.charAt(i) == ' ')
|
||||
str.append("aa");
|
||||
str.append(" ");
|
||||
|
||||
int P2 = str.length() - 1;
|
||||
while (P1 >= 0 && P2 > P1) {
|
||||
|
|
|
@ -791,12 +791,11 @@ FIFO 算法可能会把经常使用的页面置换出去,为了避免这一问
|
|||
|
||||
<div align="center"> <img src="../pics//ecf8ad5d-5403-48b9-b6e7-f2e20ffe8fca.png"/> </div><br>
|
||||
|
||||
|
||||
### 6. 时钟
|
||||
|
||||
> Clock
|
||||
|
||||
第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面链接起来,再使用一个指针指向最老的页面。
|
||||
第二次机会算法需要在链表中移动页面,降低了效率。时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。
|
||||
|
||||
<div align="center"> <img src="../pics//5f5ef0b6-98ea-497c-a007-f6c55288eab1.png"/> </div><br>
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
网络把主机连接起来,而互联网是把多种不同的网络连接起来,因此互联网是网络的网络。
|
||||
|
||||
<div align="center"> <img src="../pics//network-of-networks.gif" width="500"/> </div><br>
|
||||
<div align="center"> <img src="../pics//network-of-networks.gif" width="400"/> </div><br>
|
||||
|
||||
## ISP
|
||||
|
||||
|
@ -67,9 +67,7 @@
|
|||
|
||||
<div align="center"> <img src="../pics//46cec213-3048-4a80-aded-fdd577542801.jpg" width="500"/> </div><br>
|
||||
|
||||
目前的互联网是一种多层次 ISP 结构,ISP 根据覆盖面积的大小分为第一层 ISP、区域 ISP 和接入 ISP。
|
||||
|
||||
互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP。
|
||||
目前的互联网是一种多层次 ISP 结构,ISP 根据覆盖面积的大小分为第一层 ISP、区域 ISP 和接入 ISP。互联网交换点 IXP 允许两个 ISP 直接相连而不用经过第三个 ISP。
|
||||
|
||||
<div align="center"> <img src="../pics//168e893c-e4a0-4ba4-b81f-9d993483abd0.jpg" width="500"/> </div><br>
|
||||
|
||||
|
@ -125,7 +123,7 @@
|
|||
|
||||
## 计算机网络体系结构*
|
||||
|
||||
<div align="center"> <img src="../pics//426df589-6f97-4622-b74d-4a81fcb1da8e.png" width="800"/> </div><br>
|
||||
<div align="center"> <img src="../pics//426df589-6f97-4622-b74d-4a81fcb1da8e.png" width="600"/> </div><br>
|
||||
|
||||
### 1. 五层协议
|
||||
|
||||
|
@ -143,7 +141,7 @@
|
|||
|
||||
其中表示层和会话层用途如下:
|
||||
|
||||
- **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必担心在各台主机中数据内部格式不同的问题。
|
||||
- **表示层** :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。
|
||||
|
||||
- **会话层** :建立及管理会话。
|
||||
|
||||
|
@ -700,7 +698,7 @@ TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文
|
|||
|
||||
<div align="center"> <img src="../pics//51e2ed95-65b8-4ae9-8af3-65602d452a25.jpg" width="500"/> </div><br>
|
||||
|
||||
TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。
|
||||
TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。
|
||||
|
||||
发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。
|
||||
|
||||
|
@ -713,11 +711,11 @@ TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、
|
|||
|
||||
### 1. 慢开始与拥塞避免
|
||||
|
||||
发送的最初执行慢开始,令 cwnd=1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 ...
|
||||
发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 ...
|
||||
|
||||
注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。
|
||||
注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。
|
||||
|
||||
如果出现了超时,则令 ssthresh = cwnd/2,然后重新执行慢开始。
|
||||
如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。
|
||||
|
||||
### 2. 快重传与快恢复
|
||||
|
||||
|
@ -725,7 +723,7 @@ TCP 主要通过四种算法来进行拥塞控制:慢开始、拥塞避免、
|
|||
|
||||
在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M<sub>2</sub>,则 M<sub>3</sub> 丢失,立即重传 M<sub>3</sub>。
|
||||
|
||||
在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd/2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。
|
||||
在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。
|
||||
|
||||
慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。
|
||||
|
||||
|
@ -743,8 +741,8 @@ DNS 是一个分布式数据库,提供了主机名和 IP 地址之间相互转
|
|||
|
||||
DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53。大多数情况下 DNS 使用 UDP 进行传输,这就要求域名解析器和域名服务器都必须自己处理超时和重传来保证可靠性。在两种情况下会使用 TCP 进行传输:
|
||||
|
||||
- 如果返回的响应超过的 512 字节就改用 TCP 进行传输(UDP 最大只支持 512 字节的数据)。
|
||||
- 区域传送需要使用 TCP 进行传输(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。
|
||||
- 如果返回的响应超过的 512 字节(UDP 最大只支持 512 字节的数据)。
|
||||
- 区域传送(区域传送是主域名服务器向辅助域名服务器传送变化的那部分数据)。
|
||||
|
||||
## 文件传送协议
|
||||
|
||||
|
@ -806,7 +804,7 @@ POP3 的特点是只要用户从服务器上读取了邮件,就把该邮件删
|
|||
|
||||
### 3. IMAP
|
||||
|
||||
IMAP 协议中客户端和服务器上的邮件保持同步,如果不去手动删除邮件,那么服务器上的邮件也不会被删除。IMAP 这种做法可以让用户随时随地去访问服务器上的邮件。
|
||||
IMAP 协议中客户端和服务器上的邮件保持同步,如果不手动删除邮件,那么服务器上的邮件也不会被删除。IMAP 这种做法可以让用户随时随地去访问服务器上的邮件。
|
||||
|
||||
## 常用端口
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user