From 1672da37b0892c92cd8736fbdf95719095884ea8 Mon Sep 17 00:00:00 2001 From: guide Date: Wed, 11 Aug 2021 10:56:02 +0800 Subject: [PATCH 01/20] typo --- ...42\350\257\225\351\242\230\346\200\273\347\273\223.md" | 3 +-- ...40\345\255\246\344\271\240\346\200\273\347\273\223.md" | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git "a/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" "b/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" index 8b92632dc57..365d5aec088 100644 --- "a/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" +++ "b/docs/java/multi-thread/2020\346\234\200\346\226\260Java\345\271\266\345\217\221\350\277\233\351\230\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230\346\200\273\347\273\223.md" @@ -619,8 +619,7 @@ public ThreadPoolExecutor(int corePoolSize, 如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任时,`ThreadPoolTaskExecutor` 定义一些策略: - **`ThreadPoolExecutor.AbortPolicy`:** 抛出 `RejectedExecutionException`来拒绝新任务的处理。 -- **`ThreadPoolExecutor.CallerRunsPolicy`:** -调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。 +- **`ThreadPoolExecutor.CallerRunsPolicy`:** 调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。 - **`ThreadPoolExecutor.DiscardPolicy`:** 不处理新任务,直接丢弃掉。 - **`ThreadPoolExecutor.DiscardOldestPolicy`:** 此策略将丢弃最早的未处理的任务请求。 diff --git "a/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" "b/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" index eb266f3aac2..1adf4081fef 100644 --- "a/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" +++ "b/docs/java/multi-thread/java\347\272\277\347\250\213\346\261\240\345\255\246\344\271\240\346\200\273\347\273\223.md" @@ -173,10 +173,10 @@ public class ScheduledThreadPoolExecutor 如果当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时,`ThreadPoolTaskExecutor` 定义一些策略: -- **`ThreadPoolExecutor.AbortPolicy`**:抛出 `RejectedExecutionException`来拒绝新任务的处理。 -- **`ThreadPoolExecutor.CallerRunsPolicy`**:调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。 -- **`ThreadPoolExecutor.DiscardPolicy`:** 不处理新任务,直接丢弃掉。 -- **`ThreadPoolExecutor.DiscardOldestPolicy`:** 此策略将丢弃最早的未处理的任务请求。 +- **`ThreadPoolExecutor.AbortPolicy`** :抛出 `RejectedExecutionException`来拒绝新任务的处理。 +- **`ThreadPoolExecutor.CallerRunsPolicy`** :调用执行自己的线程运行任务,也就是直接在调用`execute`方法的线程中运行(`run`)被拒绝的任务,如果执行程序已关闭,则会丢弃该任务。因此这种策略会降低对于新任务提交速度,影响程序的整体性能。如果您的应用程序可以承受此延迟并且你要求任何一个任务请求都要被执行的话,你可以选择这个策略。 +- **`ThreadPoolExecutor.DiscardPolicy`** :不处理新任务,直接丢弃掉。 +- **`ThreadPoolExecutor.DiscardOldestPolicy`** : 此策略将丢弃最早的未处理的任务请求。 举个例子: From 3238f67bd51fa2dac8cbe42aff9905778d1ade25 Mon Sep 17 00:00:00 2001 From: guide Date: Wed, 11 Aug 2021 11:17:22 +0800 Subject: [PATCH 02/20] =?UTF-8?q?Update=20=E5=B9=B6=E5=8F=91=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=E6=80=BB=E7=BB=93.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...71\345\231\250\346\200\273\347\273\223.md" | 134 +++++++----------- 1 file changed, 51 insertions(+), 83 deletions(-) diff --git "a/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md" "b/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md" index fcc900e6ea6..e4042ebe76b 100644 --- "a/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md" +++ "b/docs/java/multi-thread/\345\271\266\345\217\221\345\256\271\345\231\250\346\200\273\347\273\223.md" @@ -1,50 +1,24 @@ -点击关注[公众号](#公众号 "公众号")及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。 - - - -- [一 JDK 提供的并发容器总结](#一-jdk-提供的并发容器总结 "一 JDK 提供的并发容器总结") -- [二 ConcurrentHashMap](#二-concurrenthashmap "二 ConcurrentHashMap") -- [三 CopyOnWriteArrayList](#三-copyonwritearraylist "三 CopyOnWriteArrayList") - - [3.1 CopyOnWriteArrayList 简介](#31-copyonwritearraylist-简介 "3.1 CopyOnWriteArrayList 简介") - - [3.2 CopyOnWriteArrayList 是如何做到的?](#32-copyonwritearraylist-是如何做到的? "3.2 CopyOnWriteArrayList 是如何做到的?") - - [3.3 CopyOnWriteArrayList 读取和写入源码简单分析](#33-copyonwritearraylist-读取和写入源码简单分析 "3.3 CopyOnWriteArrayList 读取和写入源码简单分析") - - [3.3.1 CopyOnWriteArrayList 读取操作的实现](#331-copyonwritearraylist-读取操作的实现 "3.3.1 CopyOnWriteArrayList 读取操作的实现") - - [3.3.2 CopyOnWriteArrayList 写入操作的实现](#332-copyonwritearraylist-写入操作的实现 "3.3.2 CopyOnWriteArrayList 写入操作的实现") -- [四 ConcurrentLinkedQueue](#四-concurrentlinkedqueue "四 ConcurrentLinkedQueue") -- [五 BlockingQueue](#五-blockingqueue "五 BlockingQueue") - - [5.1 BlockingQueue 简单介绍](#51-blockingqueue-简单介绍 "5.1 BlockingQueue 简单介绍") - - [5.2 ArrayBlockingQueue](#52-arrayblockingqueue "5.2 ArrayBlockingQueue") - - [5.3 LinkedBlockingQueue](#53-linkedblockingqueue "5.3 LinkedBlockingQueue") - - [5.4 PriorityBlockingQueue](#54-priorityblockingqueue "5.4 PriorityBlockingQueue") -- [六 ConcurrentSkipListMap](#六-concurrentskiplistmap "六 ConcurrentSkipListMap") -- [七 参考](#七-参考 "七 参考") - - - -## 一 JDK 提供的并发容器总结 +## JDK 提供的并发容器总结 JDK 提供的这些容器大部分在 `java.util.concurrent` 包中。 -- **ConcurrentHashMap:** 线程安全的 HashMap -- **CopyOnWriteArrayList:** 线程安全的 List,在读多写少的场合性能非常好,远远好于 Vector. -- **ConcurrentLinkedQueue:** 高效的并发队列,使用链表实现。可以看做一个线程安全的 LinkedList,这是一个非阻塞队列。 -- **BlockingQueue:** 这是一个接口,JDK 内部通过链表、数组等方式实现了这个接口。表示阻塞队列,非常适合用于作为数据共享的通道。 -- **ConcurrentSkipListMap:** 跳表的实现。这是一个 Map,使用跳表的数据结构进行快速查找。 +- **`ConcurrentHashMap`** : 线程安全的 `HashMap` +- **`CopyOnWriteArrayList`** : 线程安全的 `List`,在读多写少的场合性能非常好,远远好于 `Vector`。 +- **`ConcurrentLinkedQueue`** : 高效的并发队列,使用链表实现。可以看做一个线程安全的 `LinkedList`,这是一个非阻塞队列。 +- **`BlockingQueue`** : 这是一个接口,JDK 内部通过链表、数组等方式实现了这个接口。表示阻塞队列,非常适合用于作为数据共享的通道。 +- **`ConcurrentSkipListMap`** : 跳表的实现。这是一个 Map,使用跳表的数据结构进行快速查找。 -## 二 ConcurrentHashMap +## ConcurrentHashMap -我们知道 HashMap 不是线程安全的,在并发场景下如果要保证一种可行的方式是使用 `Collections.synchronizedMap()` 方法来包装我们的 HashMap。但这是通过使用一个全局的锁来同步不同线程间的并发访问,因此会带来不可忽视的性能问题。 +我们知道 `HashMap` 不是线程安全的,在并发场景下如果要保证一种可行的方式是使用 `Collections.synchronizedMap()` 方法来包装我们的 `HashMap`。但这是通过使用一个全局的锁来同步不同线程间的并发访问,因此会带来不可忽视的性能问题。 -所以就有了 HashMap 的线程安全版本—— ConcurrentHashMap 的诞生。在 ConcurrentHashMap 中,无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。 +所以就有了 `HashMap` 的线程安全版本—— `ConcurrentHashMap` 的诞生。 -关于 ConcurrentHashMap 相关问题,我在 [Java 集合框架常见面试题](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md "Java集合框架常见面试题") 这篇文章中已经提到过。下面梳理一下关于 ConcurrentHashMap 比较重要的问题: +在 `ConcurrentHashMap` 中,无论是读操作还是写操作都能保证很高的性能:在进行读操作时(几乎)不需要加锁,而在写操作时通过锁分段技术只对所操作的段加锁而不影响客户端对其它段的访问。 -- [ConcurrentHashMap 和 Hashtable 的区别](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md#concurrenthashmap-%E5%92%8C-hashtable-%E7%9A%84%E5%8C%BA%E5%88%AB "ConcurrentHashMap 和 Hashtable 的区别") -- [ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md#concurrenthashmap%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F%E5%BA%95%E5%B1%82%E5%85%B7%E4%BD%93%E5%AE%9E%E7%8E%B0 "ConcurrentHashMap线程安全的具体实现方式/底层具体实现") +## CopyOnWriteArrayList -## 三 CopyOnWriteArrayList - -### 3.1 CopyOnWriteArrayList 简介 +### CopyOnWriteArrayList 简介 ```java public class CopyOnWriteArrayList @@ -52,21 +26,21 @@ extends Object implements List, RandomAccess, Cloneable, Serializable ``` -在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费。我们应该允许多个线程同时访问 List 的内部数据,毕竟读取操作是安全的。 +在很多应用场景中,读操作可能会远远大于写操作。由于读操作根本不会修改原有的数据,因此对于每次读取都进行加锁其实是一种资源浪费。我们应该允许多个线程同时访问 `List` 的内部数据,毕竟读取操作是安全的。 这和我们之前在多线程章节讲过 `ReentrantReadWriteLock` 读写锁的思想非常类似,也就是读读共享、写写互斥、读写互斥、写读互斥。JDK 中提供了 `CopyOnWriteArrayList` 类比相比于在读写锁的思想又更进一步。为了将读取的性能发挥到极致,`CopyOnWriteArrayList` 读取是完全不用加锁的,并且更厉害的是:写入也不会阻塞读取操作。只有写入和写入之间需要进行同步等待。这样一来,读操作的性能就会大幅度提升。**那它是怎么做的呢?** -### 3.2 CopyOnWriteArrayList 是如何做到的? +### CopyOnWriteArrayList 是如何做到的? `CopyOnWriteArrayList` 类的所有可变操作(add,set 等等)都是通过创建底层数组的新副本来实现的。当 List 需要被修改的时候,我并不修改原有内容,而是对原有数据进行一次复制,将修改的内容写入副本。写完之后,再将修改完的副本替换原来的数据,这样就可以保证写操作不会影响读操作了。 -从 `CopyOnWriteArrayList` 的名字就能看出`CopyOnWriteArrayList` 是满足`CopyOnWrite` 的 ArrayList,所谓`CopyOnWrite` 也就是说:在计算机,如果你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了。 +从 `CopyOnWriteArrayList` 的名字就能看出 `CopyOnWriteArrayList` 是满足 `CopyOnWrite` 的。所谓 `CopyOnWrite` 也就是说:在计算机,如果你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉了。 -### 3.3 CopyOnWriteArrayList 读取和写入源码简单分析 +### CopyOnWriteArrayList 读取和写入源码简单分析 -#### 3.3.1 CopyOnWriteArrayList 读取操作的实现 +#### CopyOnWriteArrayList 读取操作的实现 -读取操作没有任何同步控制和锁操作,理由就是内部数组 array 不会发生修改,只会被另外一个 array 替换,因此可以保证数据安全。 +读取操作没有任何同步控制和锁操作,理由就是内部数组 `array` 不会发生修改,只会被另外一个 `array` 替换,因此可以保证数据安全。 ```java /** The array, accessed only via getArray/setArray. */ @@ -86,7 +60,7 @@ implements List, RandomAccess, Cloneable, Serializable #### 3.3.2 CopyOnWriteArrayList 写入操作的实现 -CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来。 +`CopyOnWriteArrayList` 写入操作 `add()`方法在添加集合的时候加了锁,保证了同步,避免了多线程写的时候会 copy 出多个副本出来。 ```java /** @@ -111,41 +85,49 @@ CopyOnWriteArrayList 写入操作 add() 方法在添加集合的时候加了锁 } ``` -## 四 ConcurrentLinkedQueue +## ConcurrentLinkedQueue -Java 提供的线程安全的 Queue 可以分为**阻塞队列**和**非阻塞队列**,其中阻塞队列的典型例子是 BlockingQueue,非阻塞队列的典型例子是 ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 **阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现。** +Java 提供的线程安全的 `Queue` 可以分为**阻塞队列**和**非阻塞队列**,其中阻塞队列的典型例子是 `BlockingQueue`,非阻塞队列的典型例子是 `ConcurrentLinkedQueue`,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 **阻塞队列可以通过加锁来实现,非阻塞队列可以通过 CAS 操作实现。** -从名字可以看出,`ConcurrentLinkedQueue`这个队列使用链表作为其数据结构.ConcurrentLinkedQueue 应该算是在高并发环境中性能最好的队列了。它之所有能有很好的性能,是因为其内部复杂的实现。 +从名字可以看出,`ConcurrentLinkedQueue`这个队列使用链表作为其数据结构.`ConcurrentLinkedQueue` 应该算是在高并发环境中性能最好的队列了。它之所有能有很好的性能,是因为其内部复杂的实现。 -ConcurrentLinkedQueue 内部代码我们就不分析了,大家知道 ConcurrentLinkedQueue 主要使用 CAS 非阻塞算法来实现线程安全就好了。 +`ConcurrentLinkedQueue` 内部代码我们就不分析了,大家知道 `ConcurrentLinkedQueue` 主要使用 CAS 非阻塞算法来实现线程安全就好了。 -ConcurrentLinkedQueue 适合在对性能要求相对较高,同时对队列的读写存在多个线程同时进行的场景,即如果对队列加锁的成本较高则适合使用无锁的 ConcurrentLinkedQueue 来替代。 +`ConcurrentLinkedQueue` 适合在对性能要求相对较高,同时对队列的读写存在多个线程同时进行的场景,即如果对队列加锁的成本较高则适合使用无锁的 `ConcurrentLinkedQueue` 来替代。 -## 五 BlockingQueue +## BlockingQueue -### 5.1 BlockingQueue 简单介绍 +### BlockingQueue 简介 -上面我们己经提到了 ConcurrentLinkedQueue 作为高性能的非阻塞队列。下面我们要讲到的是阻塞队列——BlockingQueue。阻塞队列(BlockingQueue)被广泛使用在“生产者-消费者”问题中,其原因是 BlockingQueue 提供了可阻塞的插入和移除的方法。当队列容器已满,生产者线程会被阻塞,直到队列未满;当队列容器为空时,消费者线程会被阻塞,直至队列非空时为止。 +上面我们己经提到了 `ConcurrentLinkedQueue` 作为高性能的非阻塞队列。下面我们要讲到的是阻塞队列——`BlockingQueue`。阻塞队列(`BlockingQueue`)被广泛使用在“生产者-消费者”问题中,其原因是 `BlockingQueue` 提供了可阻塞的插入和移除的方法。当队列容器已满,生产者线程会被阻塞,直到队列未满;当队列容器为空时,消费者线程会被阻塞,直至队列非空时为止。 -BlockingQueue 是一个接口,继承自 Queue,所以其实现类也可以作为 Queue 的实现来使用,而 Queue 又继承自 Collection 接口。下面是 BlockingQueue 的相关实现类: +`BlockingQueue` 是一个接口,继承自 `Queue`,所以其实现类也可以作为 `Queue` 的实现来使用,而 `Queue` 又继承自 `Collection` 接口。下面是 `BlockingQueue` 的相关实现类: ![BlockingQueue 的实现类](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-9/51622268.jpg) -**下面主要介绍一下:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,这三个 BlockingQueue 的实现类。** +下面主要介绍一下 3 个常见的 `BlockingQueue` 的实现类:`ArrayBlockingQueue`、`LinkedBlockingQueue` 、`PriorityBlockingQueue` 。 + +### ArrayBlockingQueue + +`ArrayBlockingQueue` 是 `BlockingQueue` 接口的有界队列实现类,底层采用数组来实现。 -### 5.2 ArrayBlockingQueue +```java +public class ArrayBlockingQueue +extends AbstractQueue +implements BlockingQueue, Serializable{} +``` -**ArrayBlockingQueue** 是 BlockingQueue 接口的有界队列实现类,底层采用**数组**来实现。ArrayBlockingQueue 一旦创建,容量不能改变。其并发控制采用可重入锁来控制,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。 +`ArrayBlockingQueue` 一旦创建,容量不能改变。其并发控制采用可重入锁 `ReentrantLock` ,不管是插入操作还是读取操作,都需要获取到锁才能进行操作。当队列容量满时,尝试将元素放入队列将导致操作阻塞;尝试从一个空队列中取一个元素也会同样阻塞。 -ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue。而非公平性则是指访问 ArrayBlockingQueue 的顺序不是遵守严格的时间顺序,有可能存在,当 ArrayBlockingQueue 可以被访问时,长时间阻塞的线程依然无法访问到 ArrayBlockingQueue。如果保证公平性,通常会降低吞吐量。如果需要获得公平性的 ArrayBlockingQueue,可采用如下代码: +`ArrayBlockingQueue` 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 `ArrayBlockingQueue`。而非公平性则是指访问 `ArrayBlockingQueue` 的顺序不是遵守严格的时间顺序,有可能存在,当 `ArrayBlockingQueue` 可以被访问时,长时间阻塞的线程依然无法访问到 `ArrayBlockingQueue`。如果保证公平性,通常会降低吞吐量。如果需要获得公平性的 `ArrayBlockingQueue`,可采用如下代码: ```java private static ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(10,true); ``` -### 5.3 LinkedBlockingQueue +### LinkedBlockingQueue -**LinkedBlockingQueue** 底层基于**单向链表**实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,同样满足 FIFO 的特性,与 ArrayBlockingQueue 相比起来具有更高的吞吐量,为了防止 LinkedBlockingQueue 容量迅速增,损耗大量内存。通常在创建 LinkedBlockingQueue 对象时,会指定其大小,如果未指定,容量等于 Integer.MAX_VALUE。 +`LinkedBlockingQueue` 底层基于**单向链表**实现的阻塞队列,可以当做无界队列也可以当做有界队列来使用,同样满足 FIFO 的特性,与 `ArrayBlockingQueue` 相比起来具有更高的吞吐量,为了防止 `LinkedBlockingQueue` 容量迅速增,损耗大量内存。通常在创建 `LinkedBlockingQueue` 对象时,会指定其大小,如果未指定,容量等于 `Integer.MAX_VALUE` 。 **相关构造方法:** @@ -174,25 +156,21 @@ private static ArrayBlockingQueue blockingQueue = new ArrayBlockingQueu } ``` -### 5.4 PriorityBlockingQueue - -**PriorityBlockingQueue** 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 `compareTo()` 方法来指定元素排序规则,或者初始化时通过构造器参数 `Comparator` 来指定排序规则。 +### PriorityBlockingQueue -PriorityBlockingQueue 并发控制采用的是 **ReentrantLock**,队列为无界队列(ArrayBlockingQueue 是有界队列,LinkedBlockingQueue 也可以通过在构造函数中传入 capacity 指定队列最大的容量,但是 PriorityBlockingQueue 只能指定初始的队列大小,后面插入元素的时候,**如果空间不够的话会自动扩容**)。 +`PriorityBlockingQueue` 是一个支持优先级的无界阻塞队列。默认情况下元素采用自然顺序进行排序,也可以通过自定义类实现 `compareTo()` 方法来指定元素排序规则,或者初始化时通过构造器参数 `Comparator` 来指定排序规则。 -简单地说,它就是 PriorityQueue 的线程安全版本。不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报 ClassCastException 异常。它的插入操作 put 方法不会 block,因为它是无界队列(take 方法在队列为空的时候会阻塞)。 +`PriorityBlockingQueue` 并发控制采用的是可重入锁 `ReentrantLock`,队列为无界队列(`ArrayBlockingQueue` 是有界队列,`LinkedBlockingQueue` 也可以通过在构造函数中传入 `capacity` 指定队列最大的容量,但是 `PriorityBlockingQueue` 只能指定初始的队列大小,后面插入元素的时候,**如果空间不够的话会自动扩容**)。 -**推荐文章:** +简单地说,它就是 `PriorityQueue` 的线程安全版本。不可以插入 null 值,同时,插入队列的对象必须是可比较大小的(comparable),否则报 `ClassCastException` 异常。它的插入操作 put 方法不会 block,因为它是无界队列(take 方法在队列为空的时候会阻塞)。 -《解读 Java 并发队列 BlockingQueue》 +**推荐文章:** [《解读 Java 并发队列 BlockingQueue》](https://javadoop.com/post/java-concurrent-queue) -[https://javadoop.com/post/java-concurrent-queue](https://javadoop.com/post/java-concurrent-queue "https://javadoop.com/post/java-concurrent-queue") - -## 六 ConcurrentSkipListMap +## ConcurrentSkipListMap 下面这部分内容参考了极客时间专栏[《数据结构与算法之美》](https://time.geekbang.org/column/intro/126?code=zl3GYeAsRI4rEJIBNu5B/km7LSZsPDlGWQEpAYw5Vu0=&utm_term=SPoster "《数据结构与算法之美》")以及《实战 Java 高并发程序设计》。 -**为了引出 ConcurrentSkipListMap,先带着大家简单理解一下跳表。** +为了引出 `ConcurrentSkipListMap`,先带着大家简单理解一下跳表。 对于一个单链表,即使链表是有序的,如果我们想要在其中查找某个数据,也只能从头到尾遍历链表,这样效率自然就会很低,跳表就不一样了。跳表是一种可以用来快速查找的数据结构,有点类似于平衡树。它们都可以对元素进行快速的查找。但一个重要的区别是:对平衡树的插入和删除往往很可能导致平衡树进行一次全局的调整。而对跳表的插入和删除只需要对整个数据结构的局部进行操作即可。这样带来的好处是:在高并发的情况下,你会需要一个全局锁来保证整个平衡树的线程安全。而对于跳表,你只需要部分锁即可。这样,在高并发环境下,你就可以拥有更好的性能。而就查询的性能而言,跳表的时间复杂度也是 **O(logn)** 所以在并发数据结构中,JDK 使用跳表来实现一个 Map。 @@ -210,20 +188,10 @@ PriorityBlockingQueue 并发控制采用的是 **ReentrantLock**,队列为无 从上面很容易看出,**跳表是一种利用空间换时间的算法。** -使用跳表实现 Map 和使用哈希算法实现 Map 的另外一个不同之处是:哈希并不会保存元素的顺序,而跳表内所有的元素都是排序的。因此在对跳表进行遍历时,你会得到一个有序的结果。所以,如果你的应用需要有序性,那么跳表就是你不二的选择。JDK 中实现这一数据结构的类是 ConcurrentSkipListMap。 +使用跳表实现 `Map` 和使用哈希算法实现 `Map` 的另外一个不同之处是:哈希并不会保存元素的顺序,而跳表内所有的元素都是排序的。因此在对跳表进行遍历时,你会得到一个有序的结果。所以,如果你的应用需要有序性,那么跳表就是你不二的选择。JDK 中实现这一数据结构的类是 `ConcurrentSkipListMap`。 -## 七 参考 +## 参考 - 《实战 Java 高并发程序设计》 - https://javadoop.com/post/java-concurrent-queue - https://juejin.im/post/5aeebd02518825672f19c546 - -## 公众号 - -如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。 - -**《Java 面试突击》:** 由本文档衍生的专为面试而生的《Java 面试突击》V2.0 PDF 版本[公众号](#公众号 "公众号")后台回复 **"面试突击"** 即可免费领取! - -**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。 - -![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) From e0ce9e4e6bbd93e15252f01f1201563c81661291 Mon Sep 17 00:00:00 2001 From: guide Date: Fri, 13 Aug 2021 21:38:06 +0800 Subject: [PATCH 03/20] =?UTF-8?q?Update=20=E4=BB=A3=E7=90=86=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E8=AF=A6=E8=A7=A3.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" "b/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" index 8323cedc168..704de492bef 100644 --- "a/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" +++ "b/docs/java/basis/\344\273\243\347\220\206\346\250\241\345\274\217\350\257\246\350\247\243.md" @@ -348,7 +348,7 @@ public class DebugMethodInterceptor implements MethodInterceptor { /** - * @param o 被代理的对象(需要增强的对象) + * @param o 代理对象(增强的对象) * @param method 被拦截的方法(需要增强的方法) * @param args 方法入参 * @param methodProxy 用于调用原始方法 From 4ad22b21c2d4e2bd485f89a047bde9c1d6e772f2 Mon Sep 17 00:00:00 2001 From: kaka2634 <996529090@qq.com> Date: Sat, 14 Aug 2021 01:17:45 +0800 Subject: [PATCH 04/20] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\351\235\242\350\257\225\351\242\230.md" | 32 +++++++++++------- .../images/java-collection-hierarchy.png | Bin 0 -> 90889 bytes 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 docs/java/collection/images/java-collection-hierarchy.png diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" index 5c0c5b389d7..e604f81962c 100644 --- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" +++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" @@ -50,19 +50,21 @@ ### 1.1.1. Java 集合概览 -从下图可以看出,在 Java 中除了以 `Map` 结尾的类之外, 其他类都实现了 `Collection` 接口。 +Java 集合, 也叫作容器,主要是由两大接口派生而来:一个是 `Collecton`接口,主要用于存放单一元素;另一个是 `Map` 接口,主要用于存放键值对。对于`Collection` 接口,下面又有三个主要的子接口:`List`、`Set` 和 `Queue`。 -并且,以 `Map` 结尾的类都实现了 `Map` 接口。 +Java 集合框架如下图所示: -![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/source-code/dubbo/java-collection-hierarchy.png) +![](./images/java-collection-hierarchy.png) -

https://www.javatpoint.com/collections-in-java

-### 1.1.2. 说说 List,Set,Map 三者的区别? +注:图中只列举了主要的继承派生关系,并没有列举所有关系。比方省略了`AbstractList`, `NavigableSet`等抽象类以及其他的一些辅助类,如想深入了解,可自行查看源码。 -- `List`(对付顺序的好帮手): 存储的元素是有序的、可重复的。 +### 1.1.2. 说说 List, Set, Queue, Map 四者的区别? + +- `List`(对付顺序的好帮手): 存储的元素是有序的、可重复的。 - `Set`(注重独一无二的性质): 存储的元素是无序的、不可重复的。 -- `Map`(用 Key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),“x”代表 key,"y"代表 value,Key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。 +- `Queue`(实现排队功能的叫号机): 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。 +- `Map`(用 key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),"x" 代表 key,"y" 代表 value,key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。 ### 1.1.3. 集合框架底层数据结构总结 @@ -70,19 +72,23 @@ #### 1.1.3.1. List -- `Arraylist`: `Object[]`数组 -- `Vector`:`Object[]`数组 +- `Arraylist`: `Object[]` 数组 +- `Vector`:`Object[]` 数组 - `LinkedList`: 双向链表(JDK1.6 之前为循环链表,JDK1.7 取消了循环) #### 1.1.3.2. Set -- `HashSet`(无序,唯一): 基于 `HashMap` 实现的,底层采用 `HashMap` 来保存元素 -- `LinkedHashSet`:`LinkedHashSet` 是 `HashSet` 的子类,并且其内部是通过 `LinkedHashMap` 来实现的。有点类似于我们之前说的 `LinkedHashMap` 其内部是基于 `HashMap` 实现一样,不过还是有一点点区别的 -- `TreeSet`(有序,唯一): 红黑树(自平衡的排序二叉树) +- `HashSet`(无序,唯一): 基于 `HashMap` 实现的,底层采用 `HashMap` 来保存元素 +- `LinkedHashSet`: `LinkedHashSet` 是 `HashSet` 的子类,并且其内部是通过 `LinkedHashMap` 来实现的。有点类似于我们之前说的 `LinkedHashMap` 其内部是基于 `HashMap` 实现一样,不过还是有一点点区别的 +- `TreeSet`(有序,唯一): 红黑树(自平衡的排序二叉树) + +#### 1.1.3.3 Queue +- `PriorityQueue`: `Object[]` 数组来实现二叉堆 +- `ArrayQueue`: `Object[]` 数组 + 双指针 再来看看 `Map` 接口下面的集合。 -#### 1.1.3.3. Map +#### 1.1.3.4. Map - `HashMap`: JDK1.8 之前 `HashMap` 由数组+链表组成的,数组是 `HashMap` 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间 - `LinkedHashMap`: `LinkedHashMap` 继承自 `HashMap`,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,`LinkedHashMap` 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。详细可以查看:[《LinkedHashMap 源码详细分析(JDK1.8)》](https://www.imooc.com/article/22931) diff --git a/docs/java/collection/images/java-collection-hierarchy.png b/docs/java/collection/images/java-collection-hierarchy.png new file mode 100644 index 0000000000000000000000000000000000000000..78daf9808454703816958d3e2ce52875612c7345 GIT binary patch literal 90889 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 literal 0 HcmV?d00001 From 2a4f95308de1424dcb61deb3fda2bb6af64a2748 Mon Sep 17 00:00:00 2001 From: guide Date: Sat, 14 Aug 2021 09:16:39 +0800 Subject: [PATCH 05/20] =?UTF-8?q?[feat]=20=E8=A1=A5=E5=85=85=20redis=20?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/database/Redis/redis-all.md | 120 ++++++++++--------------------- 1 file changed, 39 insertions(+), 81 deletions(-) diff --git a/docs/database/Redis/redis-all.md b/docs/database/Redis/redis-all.md index 64ea49d563a..93227374d2e 100644 --- a/docs/database/Redis/redis-all.md +++ b/docs/database/Redis/redis-all.md @@ -1,45 +1,5 @@ -点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。 - - - - - -- [1. 简单介绍一下 Redis 呗!](#1-简单介绍一下-redis-呗) -- [2. 分布式缓存常见的技术选型方案有哪些?](#2-分布式缓存常见的技术选型方案有哪些) -- [3. 说一下 Redis 和 Memcached 的区别和共同点](#3-说一下-redis-和-memcached-的区别和共同点) -- [4. 缓存数据的处理流程是怎样的?](#4-缓存数据的处理流程是怎样的) -- [5. 为什么要用 Redis/为什么要用缓存?](#5-为什么要用-redis为什么要用缓存) -- [6. Redis 常见数据结构以及使用场景分析](#6-redis-常见数据结构以及使用场景分析) - - [6.1. string](#61-string) - - [6.2. list](#62-list) - - [6.3. hash](#63-hash) - - [6.4. set](#64-set) - - [6.5. sorted set](#65-sorted-set) - - [6.6 bitmap](#66-bitmap) -- [7. Redis 单线程模型详解](#7-redis-单线程模型详解) -- [8. Redis 没有使用多线程?为什么不使用多线程?](#8-redis-没有使用多线程为什么不使用多线程) -- [9. Redis6.0 之后为何引入了多线程?](#9-redis60-之后为何引入了多线程) -- [10. Redis 给缓存数据设置过期时间有啥用?](#10-redis-给缓存数据设置过期时间有啥用) -- [11. Redis 是如何判断数据是否过期的呢?](#11-redis-是如何判断数据是否过期的呢) -- [12. 过期的数据的删除策略了解么?](#12-过期的数据的删除策略了解么) -- [13. Redis 内存淘汰机制了解么?](#13-redis-内存淘汰机制了解么) -- [14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)](#14-redis-持久化机制怎么保证-redis-挂掉之后再重启数据可以进行恢复) -- [15. Redis 事务](#15-redis-事务) -- [16. 缓存穿透](#16-缓存穿透) - - [16.1. 什么是缓存穿透?](#161-什么是缓存穿透) - - [16.2. 缓存穿透情况的处理流程是怎样的?](#162-缓存穿透情况的处理流程是怎样的) - - [16.3. 有哪些解决办法?](#163-有哪些解决办法) -- [17. 缓存雪崩](#17-缓存雪崩) - - [17.1. 什么是缓存雪崩?](#171-什么是缓存雪崩) - - [17.2. 有哪些解决办法?](#172-有哪些解决办法) -- [18. 如何保证缓存和数据库数据的一致性?](#18-如何保证缓存和数据库数据的一致性) -- [19. 参考](#19-参考) -- [20. 公众号](#20-公众号) - - - - -### 1. 简单介绍一下 Redis 呗! + +### 简单介绍一下 Redis 呗! 简单来说 **Redis 就是一个使用 C 语言开发的数据库**,不过与传统数据库不同的是 **Redis 的数据是存在内存中的** ,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。 @@ -47,7 +7,7 @@ **Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。** -### 2. 分布式缓存常见的技术选型方案有哪些? +### 分布式缓存常见的技术选型方案有哪些? 分布式缓存的话,使用的比较多的主要是 **Memcached** 和 **Redis**。不过,现在基本没有看过还有项目使用 **Memcached** 来做缓存,都是直接用 **Redis**。 @@ -55,7 +15,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来 分布式缓存主要解决的是单机缓存的容量受服务器限制并且无法保存通用信息的问题。因为,本地缓存只在当前服务里有效,比如如果你部署了两个相同的服务,他们两者之间的缓存数据是无法共同的。 -### 3. 说一下 Redis 和 Memcached 的区别和共同点 +### 说一下 Redis 和 Memcached 的区别和共同点 现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!不过,了解 Redis 和 Memcached 的区别和共同点,有助于我们在做相应的技术选型的时候,能够做到有理有据! @@ -78,7 +38,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来 相信看了上面的对比之后,我们已经没有什么理由可以选择使用 Memcached 来作为自己项目的分布式缓存了。 -### 4. 缓存数据的处理流程是怎样的? +### 缓存数据的处理流程是怎样的? 作为暖男一号,我给大家画了一个草图。 @@ -91,7 +51,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来 3. 数据库中存在的话就更新缓存中的数据。 4. 数据库中不存在的话就返回空数据。 -### 5. 为什么要用 Redis/为什么要用缓存? +### 为什么要用 Redis/为什么要用缓存? _简单,来说使用缓存主要是为了提升用户体验以及应对更多的用户。_ @@ -117,13 +77,21 @@ _简单,来说使用缓存主要是为了提升用户体验以及应对更多 由此可见,直接操作缓存能够承受的数据库请求数量是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。进而,我们也就提高了系统整体的并发。 -### 6. Redis 常见数据结构以及使用场景分析 +### Redis 除了做缓存,还能做什么? + +- **分布式锁** : 通过 Redis 来做分布式锁是一种比较常见的方式。通常情况下,我们都是基于 Redisson 来实现分布式锁。相关阅读:[《分布式锁中的王者方案 - Redisson》](https://mp.weixin.qq.com/s/CbnPRfvq4m1sqo2uKI6qQw)。 +- **限流** :一般是通过 Redis + Lua 脚本的方式来实现限流。相关阅读:[《我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了!》](https://mp.weixin.qq.com/s/kyFAWH3mVNJvurQDt4vchA)。 +- **消息队列** :Redis 自带的 list 数据结构可以作为一个简单的队列使用。Redis5.0 中增加的 Stream 类型的数据结构更加适合用来做消息队列。它比较类似于 Kafka,有主题和消费组的概念,支持消息持久化以及 ACK 机制。 +- **复杂业务场景** :通过 Redis 以及 Redis 扩展(比如 Redisson)提供的数据结构,我们可以很方便地完成很多复杂的业务场景比如通过 bitmap 统计活跃用户、通过 sorted set 维护排行榜。 +- ...... + +### Redis 常见数据结构以及使用场景分析 你可以自己本机安装 redis 或者通过 redis 官网提供的[在线 redis 环境](https://try.redis.io/)。 ![try-redis](./images/redis-all/try-redis.png) -#### 6.1. string +#### string 1. **介绍** :string 数据结构是简单的 key-value 类型。虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 **简单动态字符串**(simple dynamic string,**SDS**)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。 2. **常用命令:** `set,get,strlen,exists,decr,incr,setex` 等等。 @@ -184,7 +152,7 @@ OK (integer) 56 ``` -#### 6.2. list +#### list 1. **介绍** :**list** 即是 **链表**。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 **LinkedList**,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。 2. **常用命令:** `rpush,lpop,lpush,rpop,lrange,llen` 等。 @@ -245,7 +213,7 @@ OK (integer) 3 ``` -#### 6.3. hash +#### hash 1. **介绍** :hash 类似于 JDK1.8 前的 HashMap,内部实现也差不多(数组 + 链表)。不过,Redis 的 hash 做了更多优化。另外,hash 是一个 string 类型的 field 和 value 的映射表,**特别适合用于存储对象**,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以 hash 数据结构来存储用户信息,商品信息等等。 2. **常用命令:** `hset,hmset,hexists,hget,hgetall,hkeys,hvals` 等。 @@ -282,7 +250,7 @@ OK "GuideGeGe" ``` -#### 6.4. set +#### set 1. **介绍 :** set 类似于 Java 中的 `HashSet` 。Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序。当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。比如:你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。 2. **常用命令:** `sadd,spop,smembers,sismember,scard,sinterstore,sunion` 等。 @@ -310,7 +278,7 @@ OK 1) "value2" ``` -#### 6.5. sorted set +#### sorted set 1. **介绍:** 和 set 相比,sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。有点像是 Java 中 HashMap 和 TreeSet 的结合体。 2. **常用命令:** `zadd,zcard,zscore,zrange,zrevrange,zrem` 等。 @@ -337,7 +305,7 @@ OK 2) "value2" ``` -#### 6.6 bitmap +#### bitmap 1. **介绍:** bitmap 存储的是连续的二进制数字(0 和 1),通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 bitmap 本身会极大的节省储存空间。 2. **常用命令:** `setbit` 、`getbit` 、`bitcount`、`bitop` @@ -417,7 +385,7 @@ BITOP operation destkey key [key ...] 只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。 -### 7. Redis 单线程模型详解 +### Redis 单线程模型详解 **Redis 基于 Reactor 模式来设计开发了自己的一套高效的事件处理模型** (Netty 的线程模型也基于 Reactor 模式,Reactor 模式不愧是高性能 IO 的基石),这套事件处理模型对应的是 Redis 中的文件事件处理器(file event handler)。由于文件事件处理器(file event handler)是单线程方式运行的,所以我们一般都说 Redis 是单线程模型。 @@ -450,7 +418,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(

《Redis设计与实现:12章》

-### 8. Redis 没有使用多线程?为什么不使用多线程? +### Redis 没有使用多线程?为什么不使用多线程? 虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。** @@ -468,7 +436,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接( 2. Redis 的性能瓶颈不在 CPU ,主要在内存和网络; 3. 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。 -### 9. Redis6.0 之后为何引入了多线程? +### Redis6.0 之后为何引入了多线程? **Redis6.0 引入多线程主要是为了提高网络 IO 读写性能**,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。 @@ -491,7 +459,7 @@ io-threads 4 #官网建议4核的机器建议设置为2或3个线程,8核的 1. [Redis 6.0 新特性-多线程连环 13 问!](https://mp.weixin.qq.com/s/FZu3acwK6zrCBZQ_3HoUgw) 2. [为什么 Redis 选择单线程模型](https://draveness.me/whys-the-design-redis-single-thread/) -### 10. Redis 给缓存数据设置过期时间有啥用? +### Redis 给缓存数据设置过期时间有啥用? 一般情况下,我们设置保存的缓存数据的时候都会设置一个过期时间。为什么呢? @@ -516,7 +484,7 @@ OK 如果使用传统的数据库来处理的话,一般都是自己判断过期,这样更麻烦并且性能要差很多。 -### 11. Redis 是如何判断数据是否过期的呢? +### Redis 是如何判断数据是否过期的呢? Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。 @@ -534,7 +502,7 @@ typedef struct redisDb { } redisDb; ``` -### 12. 过期的数据的删除策略了解么? +### 过期的数据的删除策略了解么? 如果假设你设置了一批 key 只能存活 1 分钟,那么 1 分钟后,Redis 是怎么对这批 key 进行删除的呢? @@ -549,7 +517,7 @@ typedef struct redisDb { 怎么解决这个问题呢?答案就是:**Redis 内存淘汰机制。** -### 13. Redis 内存淘汰机制了解么? +### Redis 内存淘汰机制了解么? > 相关问题:MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据? @@ -567,7 +535,7 @@ Redis 提供 6 种数据淘汰策略: 7. **volatile-lfu(least frequently used)**:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰 8. **allkeys-lfu(least frequently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key -### 14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复) +### Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复) 很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。 @@ -629,7 +597,7 @@ AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的 在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。 -### 15. Redis 事务 +### Redis 事务 Redis 可以通过 **`MULTI`,`EXEC`,`DISCARD` 和 `WATCH`** 等命令来实现事务(transaction)功能。 @@ -704,19 +672,19 @@ Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis - [issue452: 关于 Redis 事务不满足原子性的问题](https://github.com/Snailclimb/JavaGuide/issues/452) 。 - [Issue491:关于 redis 没有事务回滚?](https://github.com/Snailclimb/JavaGuide/issues/491) -### 16. 缓存穿透 +### 缓存穿透 -#### 16.1. 什么是缓存穿透? +#### 什么是缓存穿透? 缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。举个例子:某个黑客故意制造我们缓存中不存在的 key 发起大量请求,导致大量请求落到数据库。 -#### 16.2. 缓存穿透情况的处理流程是怎样的? +#### 缓存穿透情况的处理流程是怎样的? 如下图所示,用户的请求最终都要跑到数据库中查询一遍。 ![缓存穿透情况](./images/redis-all/缓存穿透情况.png) -#### 16.3. 有哪些解决办法? +#### 有哪些解决办法? 最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。 @@ -777,9 +745,9 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理 更多关于布隆过滤器的内容可以看我的这篇原创:[《不了解布隆过滤器?一文给你整的明明白白!》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/dataStructures-algorithms/data-structure/bloom-filter.md) ,强烈推荐,个人感觉网上应该找不到总结的这么明明白白的文章了。 -### 17. 缓存雪崩 +### 缓存雪崩 -#### 17.1. 什么是缓存雪崩? +#### 什么是缓存雪崩? 我发现缓存雪崩这名字起的有点意思,哈哈。 @@ -791,7 +759,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理 举个例子 :秒杀开始 12 个小时之前,我们统一存放了一批商品到 Redis 中,设置的缓存过期时间也是 12 个小时,那么秒杀开始的时候,这些秒杀的商品的访问直接就失效了。导致的情况就是,相应的请求直接就落到了数据库上,就像雪崩一样可怕。 -#### 17.2. 有哪些解决办法? +#### 有哪些解决办法? **针对 Redis 服务不可用的情况:** @@ -803,7 +771,7 @@ _为什么会出现误判的情况呢? 我们还要从布隆过滤器的原理 1. 设置不同的失效时间比如随机设置缓存的失效时间。 2. 缓存永不失效。 -### 18. 如何保证缓存和数据库数据的一致性? +### 如何保证缓存和数据库数据的一致性? 细说的话可以扯很多,但是我觉得其实没太大必要(小声 BB:很多解决方案我也没太弄明白)。我个人觉得引入缓存之后,如果为了短时间的不一致性问题,选择让系统设计变得更加复杂的话,完全没必要。 @@ -816,20 +784,10 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删 1. **缓存失效时间变短(不推荐,治标不治本)** :我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。 2. **增加 cache 更新重试机制(常用)**: 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可。 -### 19. 参考 +### 参考 - 《Redis 开发与运维》 - 《Redis 设计与实现》 - Redis 命令总结:http://Redisdoc.com/string/set.html - 通俗易懂的 Redis 数据结构基础教程:[https://juejin.im/post/5b53ee7e5188251aaa2d2e16](https://juejin.im/post/5b53ee7e5188251aaa2d2e16) - WHY Redis choose single thread (vs multi threads): [https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153](https://medium.com/@jychen7/sharing-redis-single-thread-vs-multi-threads-5870bd44d153) - -### 20. 公众号 - -如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。 - -**《Java 面试突击》:** 由本文档衍生的专为面试而生的《Java 面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java 面试突击"** 即可免费领取! - -**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。 - -![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) \ No newline at end of file From 2e813341619f8d92eaae850f78005a63b9629f80 Mon Sep 17 00:00:00 2001 From: guide Date: Sat, 14 Aug 2021 10:05:36 +0800 Subject: [PATCH 06/20] =?UTF-8?q?Update=20=E4=B8=87=E5=AD=97=E8=AF=A6?= =?UTF-8?q?=E8=A7=A3ThreadLocal=E5=85=B3=E9=94=AE=E5=AD=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...al\345\205\263\351\224\256\345\255\227.md" | 124 ++++++++---------- 1 file changed, 58 insertions(+), 66 deletions(-) diff --git "a/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md" "b/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md" index 3650ddbb25e..a7c79807775 100644 --- "a/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md" +++ "b/docs/java/multi-thread/\344\270\207\345\255\227\350\257\246\350\247\243ThreadLocal\345\205\263\351\224\256\345\255\227.md" @@ -1,19 +1,19 @@ -> 本文来自一枝花算不算浪漫投稿, 原文地址:[https://juejin.im/post/5eacc1c75188256d976df748](https://juejin.im/post/5eacc1c75188256d976df748)。 +> 本文来自一枝花算不算浪漫投稿, 原文地址:[https://juejin.im/post/5eacc1c75188256d976df748](https://juejin.im/post/5eacc1c75188256d976df748)。 ### 前言 ![](./images/thread-local/1.png) -**全文共10000+字,31张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家点点关注+在看,感谢。** +**全文共 10000+字,31 张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家点点关注+在看,感谢。** 对于`ThreadLocal`,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下: -- `ThreadLocal`的key是**弱引用**,那么在 `ThreadLocal`.get()的时候,发生**GC**之后,key是否为**null**? +- `ThreadLocal`的 key 是**弱引用**,那么在 `ThreadLocal`.get()的时候,发生**GC**之后,key 是否为**null**? - `ThreadLocal`中`ThreadLocalMap`的**数据结构**? -- `ThreadLocalMap`的**Hash算法**? -- `ThreadLocalMap`中**Hash冲突**如何解决? +- `ThreadLocalMap`的**Hash 算法**? +- `ThreadLocalMap`中**Hash 冲突**如何解决? - `ThreadLocalMap`的**扩容机制**? -- `ThreadLocalMap`中**过期key的清理机制**?**探测式清理**和**启发式清理**流程? +- `ThreadLocalMap`中**过期 key 的清理机制**?**探测式清理**和**启发式清理**流程? - `ThreadLocalMap.set()`方法实现原理? - `ThreadLocalMap.get()`方法实现原理? - 项目中`ThreadLocal`使用情况?遇到的坑? @@ -23,8 +23,6 @@ ### 目录 - - **注明:** 本文源码基于`JDK 1.8` ### `ThreadLocal`代码演示 @@ -80,19 +78,18 @@ size: 0 我们还要注意`Entry`, 它的`key`是`ThreadLocal k` ,继承自`WeakReference`, 也就是我们常说的弱引用类型。 -### GC 之后key是否为null? +### GC 之后 key 是否为 null? 回应开头的那个问题, `ThreadLocal` 的`key`是弱引用,那么在`ThreadLocal.get()`的时候,发生`GC`之后,`key`是否是`null`? 为了搞清楚这个问题,我们需要搞清楚`Java`的**四种引用类型**: -- **强引用**:我们常常new出来的对象就是强引用类型,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候 -- **软引用**:使用SoftReference修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收 -- **弱引用**:使用WeakReference修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收 +- **强引用**:我们常常 new 出来的对象就是强引用类型,只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足的时候 +- **软引用**:使用 SoftReference 修饰的对象被称为软引用,软引用指向的对象在内存要溢出的时候被回收 +- **弱引用**:使用 WeakReference 修饰的对象被称为弱引用,只要发生垃圾回收,若这个对象只被弱引用指向,那么就会被回收 - **虚引用**:虚引用是最弱的引用,在 Java 中使用 PhantomReference 进行定义。虚引用中唯一的作用就是用队列接收对象即将死亡的通知 - -接着再来看下代码,我们使用反射的方式来看看`GC`后`ThreadLocal`中的数据情况:(下面代码来源自:https://blog.csdn.net/thewindkee/article/details/103726942 本地运行演示GC回收场景) +接着再来看下代码,我们使用反射的方式来看看`GC`后`ThreadLocal`中的数据情况:(下面代码来源自:https://blog.csdn.net/thewindkee/article/details/103726942 本地运行演示 GC 回收场景) ```java public class ThreadLocalDemo { @@ -140,6 +137,7 @@ public class ThreadLocalDemo { ``` 结果如下: + ```java 弱引用key:java.lang.ThreadLocal@433619b6,值:abc 弱引用key:java.lang.ThreadLocal@418a15e3,值:java.lang.ref.SoftReference@bf97a12 @@ -192,7 +190,7 @@ void createMap(Thread t, T firstValue) { 主要的核心逻辑还是在`ThreadLocalMap`中的,一步步往下看,后面还有更详细的剖析。 -### `ThreadLocalMap` Hash算法 +### `ThreadLocalMap` Hash 算法 既然是`Map`结构,那么`ThreadLocalMap`当然也要实现自己的`hash`算法来解决散列表数组冲突问题。 @@ -200,7 +198,7 @@ void createMap(Thread t, T firstValue) { int i = key.threadLocalHashCode & (len-1); ``` -`ThreadLocalMap`中`hash`算法很简单,这里`i`就是当前key在散列表中对应的数组下标位置。 +`ThreadLocalMap`中`hash`算法很简单,这里`i`就是当前 key 在散列表中对应的数组下标位置。 这里最关键的就是`threadLocalHashCode`值的计算,`ThreadLocal`中有一个属性为`HASH_INCREMENT = 0x61c88647` @@ -215,7 +213,7 @@ public class ThreadLocal { private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); } - + static class ThreadLocalMap { ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; @@ -231,7 +229,7 @@ public class ThreadLocal { 每当创建一个`ThreadLocal`对象,这个`ThreadLocal.nextHashCode` 这个值就会增长 `0x61c88647` 。 -这个值很特殊,它是**斐波那契数** 也叫 **黄金分割数**。`hash`增量为 这个数字,带来的好处就是 `hash` **分布非常均匀**。 +这个值很特殊,它是**斐波那契数** 也叫 **黄金分割数**。`hash`增量为 这个数字,带来的好处就是 `hash` **分布非常均匀**。 我们自己可以尝试下: @@ -239,7 +237,7 @@ public class ThreadLocal { 可以看到产生的哈希码分布很均匀,这里不去细纠**斐波那契**具体算法,感兴趣的可以自行查阅相关资料。 -### `ThreadLocalMap` Hash冲突 +### `ThreadLocalMap` Hash 冲突 > **注明:** 下面所有示例图中,**绿色块**`Entry`代表**正常数据**,**灰色块**代表`Entry`的`key`值为`null`,**已被垃圾回收**。**白色块**表示`Entry`为`null`。 @@ -247,22 +245,21 @@ public class ThreadLocal { `HashMap`中解决冲突的方法是在数组上构造一个**链表**结构,冲突的数据挂载到链表上,如果链表长度超过一定数量则会转化成**红黑树**。 -而`ThreadLocalMap`中并没有链表结构,所以这里不能适用`HashMap`解决冲突的方式了。 +而 `ThreadLocalMap` 中并没有链表结构,所以这里不能使用 `HashMap` 解决冲突的方式了。 ![](./images/thread-local/7.png) +如上图所示,如果我们插入一个`value=27`的数据,通过 `hash` 计算后应该落入第 4 个槽位中,而槽位 4 已经有了 `Entry` 数据。 -如上图所示,如果我们插入一个`value=27`的数据,通过`hash`计算后应该落入第4个槽位中,而槽位4已经有了`Entry`数据。 - -此时就会线性向后查找,一直找到`Entry`为`null`的槽位才会停止查找,将当前元素放入此槽位中。当然迭代过程中还有其他的情况,比如遇到了`Entry`不为`null`且`key`值相等的情况,还有`Entry`中的`key`值为`null`的情况等等都会有不同的处理,后面会一一详细讲解。 +此时就会线性向后查找,一直找到 `Entry` 为 `null` 的槽位才会停止查找,将当前元素放入此槽位中。当然迭代过程中还有其他的情况,比如遇到了 `Entry` 不为 `null` 且 `key` 值相等的情况,还有 `Entry` 中的 `key` 值为 `null` 的情况等等都会有不同的处理,后面会一一详细讲解。 -这里还画了一个`Entry`中的`key`为`null`的数据(**Entry=2的灰色块数据**),因为`key`值是**弱引用**类型,所以会有这种数据存在。在`set`过程中,如果遇到了`key`过期的`Entry`数据,实际上是会进行一轮**探测式清理**操作的,具体操作方式后面会讲到。 +这里还画了一个`Entry`中的`key`为`null`的数据(**Entry=2 的灰色块数据**),因为`key`值是**弱引用**类型,所以会有这种数据存在。在`set`过程中,如果遇到了`key`过期的`Entry`数据,实际上是会进行一轮**探测式清理**操作的,具体操作方式后面会讲到。 ### `ThreadLocalMap.set()`详解 #### `ThreadLocalMap.set()`原理图解 -看完了`ThreadLocal` **hash算法**后,我们再来看`set`是如何实现的。 +看完了`ThreadLocal` **hash 算法**后,我们再来看`set`是如何实现的。 往`ThreadLocalMap`中`set`数据(**新增**或者**更新**数据)分为好几种情况,针对不同的情况我们画图来说说明。 @@ -282,36 +279,33 @@ public class ThreadLocal { ![](./images/thread-local/11.png) -遍历散列数组,线性往后查找,如果找到`Entry`为`null`的槽位,则将数据放入该槽位中,或者往后遍历过程中,遇到了**key值相等**的数据,直接更新即可。 +遍历散列数组,线性往后查找,如果找到`Entry`为`null`的槽位,则将数据放入该槽位中,或者往后遍历过程中,遇到了**key 值相等**的数据,直接更新即可。 **第四种情况:** 槽位数据不为空,往后遍历过程中,在找到`Entry`为`null`的槽位之前,遇到`key`过期的`Entry`,如下图,往后遍历过程中,一到了`index=7`的槽位数据`Entry`的`key=null`: ![](./images/thread-local/12.png) -散列数组下标为7位置对应的`Entry`数据`key`为`null`,表明此数据`key`值已经被垃圾回收掉了,此时就会执行`replaceStaleEntry()`方法,该方法含义是**替换过期数据的逻辑**,以**index=7**位起点开始遍历,进行探测式数据清理工作。 +散列数组下标为 7 位置对应的`Entry`数据`key`为`null`,表明此数据`key`值已经被垃圾回收掉了,此时就会执行`replaceStaleEntry()`方法,该方法含义是**替换过期数据的逻辑**,以**index=7**位起点开始遍历,进行探测式数据清理工作。 初始化探测式清理过期数据扫描的开始位置:`slotToExpunge = staleSlot = 7` 以当前`staleSlot`开始 向前迭代查找,找其他过期的数据,然后更新过期数据起始扫描下标`slotToExpunge`。`for`循环迭代,直到碰到`Entry`为`null`结束。 -如果找到了过期的数据,继续向前迭代,直到遇到`Entry=null`的槽位才停止迭代,如下图所示,**slotToExpunge被更新为0**: +如果找到了过期的数据,继续向前迭代,直到遇到`Entry=null`的槽位才停止迭代,如下图所示,**slotToExpunge 被更新为 0**: ![](./images/thread-local/13.png) -以当前节点(`index=7`)向前迭代,检测是否有过期的`Entry`数据,如果有则更新`slotToExpunge`值。碰到`null`则结束探测。以上图为例`slotToExpunge`被更新为0。 +以当前节点(`index=7`)向前迭代,检测是否有过期的`Entry`数据,如果有则更新`slotToExpunge`值。碰到`null`则结束探测。以上图为例`slotToExpunge`被更新为 0。 上面向前迭代的操作是为了更新探测清理过期数据的起始下标`slotToExpunge`的值,这个值在后面会讲解,它是用来判断当前过期槽位`staleSlot`之前是否还有过期元素。 -接着开始以`staleSlot`位置(index=7)向后迭代,**如果找到了相同key值的Entry数据:** +接着开始以`staleSlot`位置(index=7)向后迭代,**如果找到了相同 key 值的 Entry 数据:** ![](./images/thread-local/14.png) 从当前节点`staleSlot`向后查找`key`值相等的`Entry`元素,找到后更新`Entry`的值并交换`staleSlot`元素的位置(`staleSlot`位置为过期元素),更新`Entry`数据,然后开始进行过期`Entry`的清理工作,如下图所示: -![Yu4oWT.png](https://user-gold-cdn.xitu.io/2020/5/8/171f3ba9af057e1e?w=1336&h=361&f=png&s=63049) - - -**向后遍历过程中,如果没有找到相同key值的Entry数据:** +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/view.png)向后遍历过程中,如果没有找到相同 key 值的 Entry 数据: ![](./images/thread-local/15.png) @@ -367,6 +361,7 @@ int i = key.threadLocalHashCode & (len-1); ``` 什么情况下桶才是可以使用的呢? + 1. `k = key` 说明是替换操作,可以使用 2. 碰到一个过期的桶,执行替换逻辑,占用过期桶 3. 查找过程中,碰到桶中`Entry=null`的情况,直接使用 @@ -386,16 +381,17 @@ private static int prevIndex(int i, int len) { ``` 接着看剩下`for`循环中的逻辑: + 1. 遍历当前`key`值对应的桶中`Entry`数据为空,这说明散列数组这里没有数据冲突,跳出`for`循环,直接`set`数据到对应的桶中 2. 如果`key`值对应的桶中`Entry`数据不为空 -2.1 如果`k = key`,说明当前`set`操作是一个替换操作,做替换逻辑,直接返回 -2.2 如果`key = null`,说明当前桶位置的`Entry`是过期数据,执行`replaceStaleEntry()`方法(核心方法),然后返回 + 2.1 如果`k = key`,说明当前`set`操作是一个替换操作,做替换逻辑,直接返回 + 2.2 如果`key = null`,说明当前桶位置的`Entry`是过期数据,执行`replaceStaleEntry()`方法(核心方法),然后返回 3. `for`循环执行完毕,继续往下执行说明向后迭代的过程中遇到了`entry`为`null`的情况 -3.1 在`Entry`为`null`的桶中创建一个新的`Entry`对象 -3.2 执行`++size`操作 + 3.1 在`Entry`为`null`的桶中创建一个新的`Entry`对象 + 3.2 执行`++size`操作 4. 调用`cleanSomeSlots()`做一次启发式清理工作,清理散列数组中`Entry`的`key`过期的数据 -4.1 如果清理工作完成后,未清理到任何数据,且`size`超过了阈值(数组长度的2/3),进行`rehash()`操作 -4.2 `rehash()`中会先进行一轮探测式清理,清理过期`key`,清理完成后如果**size >= threshold - threshold / 4**,就会执行真正的扩容逻辑(扩容逻辑往后看) + 4.1 如果清理工作完成后,未清理到任何数据,且`size`超过了阈值(数组长度的 2/3),进行`rehash()`操作 + 4.2 `rehash()`中会先进行一轮探测式清理,清理过期`key`,清理完成后如果**size >= threshold - threshold / 4**,就会执行真正的扩容逻辑(扩容逻辑往后看) 接着重点看下`replaceStaleEntry()`方法,`replaceStaleEntry()`方法提供替换过期数据的功能,我们可以对应上面**第四种情况**的原理图来再回顾下,具体代码如下: @@ -446,7 +442,7 @@ private void replaceStaleEntry(ThreadLocal key, Object value, } ``` -`slotToExpunge`表示开始探测式清理过期数据的开始下标,默认从当前的`staleSlot`开始。以当前的`staleSlot`开始,向前迭代查找,找到没有过期的数据,`for`循环一直碰到`Entry`为`null`才会结束。如果向前找到了过期数据,更新探测清理过期数据的开始下标为i,即`slotToExpunge=i` +`slotToExpunge`表示开始探测式清理过期数据的开始下标,默认从当前的`staleSlot`开始。以当前的`staleSlot`开始,向前迭代查找,找到没有过期的数据,`for`循环一直碰到`Entry`为`null`才会结束。如果向前找到了过期数据,更新探测清理过期数据的开始下标为 i,即`slotToExpunge=i` ```java for (int i = prevIndex(staleSlot, len); @@ -460,7 +456,7 @@ for (int i = prevIndex(staleSlot, len); ``` 接着开始从`staleSlot`向后查找,也是碰到`Entry`为`null`的桶结束。 -如果迭代过程中,**碰到k == key**,这说明这里是替换逻辑,替换新数据并且交换当前`staleSlot`位置。如果`slotToExpunge == staleSlot`,这说明`replaceStaleEntry()`一开始向前查找过期数据时并未找到过期的`Entry`数据,接着向后查找过程中也未发现过期数据,修改开始探测式清理过期数据的下标为当前循环的index,即`slotToExpunge = i`。最后调用`cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);`进行启发式过期数据清理。 +如果迭代过程中,**碰到 k == key**,这说明这里是替换逻辑,替换新数据并且交换当前`staleSlot`位置。如果`slotToExpunge == staleSlot`,这说明`replaceStaleEntry()`一开始向前查找过期数据时并未找到过期的`Entry`数据,接着向后查找过程中也未发现过期数据,修改开始探测式清理过期数据的下标为当前循环的 index,即`slotToExpunge = i`。最后调用`cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);`进行启发式过期数据清理。 ```java if (k == key) { @@ -468,7 +464,7 @@ if (k == key) { tab[i] = tab[staleSlot]; tab[staleSlot] = e; - + if (slotToExpunge == staleSlot) slotToExpunge = i; @@ -479,7 +475,7 @@ if (k == key) { `cleanSomeSlots()`和`expungeStaleEntry()`方法后面都会细讲,这两个是和清理相关的方法,一个是过期`key`相关`Entry`的启发式清理(`Heuristically scan`),另一个是过期`key`相关`Entry`的探测式清理。 -**如果k != key**则会接着往下走,`k == null`说明当前遍历的`Entry`是一个过期数据,`slotToExpunge == staleSlot`说明,一开始的向前查找数据并未找到过期的`Entry`。如果条件成立,则更新`slotToExpunge` 为当前位置,这个前提是前驱节点扫描时未发现过期数据。 +**如果 k != key**则会接着往下走,`k == null`说明当前遍历的`Entry`是一个过期数据,`slotToExpunge == staleSlot`说明,一开始的向前查找数据并未找到过期的`Entry`。如果条件成立,则更新`slotToExpunge` 为当前位置,这个前提是前驱节点扫描时未发现过期数据。 ```java if (k == null && slotToExpunge == staleSlot) @@ -494,12 +490,13 @@ tab[staleSlot] = new Entry(key, value); ``` 最后判断除了`staleSlot`以外,还发现了其他过期的`slot`数据,就要开启清理数据的逻辑: + ```java if (slotToExpunge != staleSlot) cleanSomeSlots(expungeStaleEntry(slotToExpunge), len); ``` -### `ThreadLocalMap`过期key的探测式清理流程 +### `ThreadLocalMap`过期 key 的探测式清理流程 上面我们有提及`ThreadLocalMap`的两种过期`key`数据清理方式:**探测式清理**和**启发式清理**。 @@ -507,7 +504,7 @@ if (slotToExpunge != staleSlot) ![](./images/thread-local/18.png) -如上图,`set(27)` 经过hash计算后应该落到`index=4`的桶中,由于`index=4`桶已经有了数据,所以往后迭代最终数据放入到`index=7`的桶中,放入后一段时间后`index=5`中的`Entry`数据`key`变为了`null` +如上图,`set(27)` 经过 hash 计算后应该落到`index=4`的桶中,由于`index=4`桶已经有了数据,所以往后迭代最终数据放入到`index=7`的桶中,放入后一段时间后`index=5`中的`Entry`数据`key`变为了`null` ![](./images/thread-local/19.png) @@ -529,7 +526,7 @@ if (slotToExpunge != staleSlot) ![](./images/thread-local/22.png) -执行完第二步后,index=4的元素挪到index=3的槽位中。 +执行完第二步后,index=4 的元素挪到 index=3 的槽位中。 继续往后迭代检查,碰到正常数据,计算该数据位置是否偏移,如果被偏移,则重新计算`slot`位置,目的是让正常数据尽可能存放在正确位置或离正确位置更近的位置 @@ -581,7 +578,7 @@ if (k == null) { e.value = null; tab[i] = null; size--; -} +} ``` 如果`key`没有过期,重新计算当前`key`的下标位置是不是当前槽位下标位置,如果不是,那么说明产生了`hash`冲突,此时以新计算出来正确的槽位位置往后迭代,找到最近一个可以存放`entry`的位置。 @@ -686,7 +683,7 @@ private void resize() { ![](./images/thread-local/27.png) -我们以`get(ThreadLocal1)`为例,通过`hash`计算后,正确的`slot`位置应该是4,而`index=4`的槽位已经有了数据,且`key`值不等于`ThreadLocal1`,所以需要继续往后迭代查找。 +我们以`get(ThreadLocal1)`为例,通过`hash`计算后,正确的`slot`位置应该是 4,而`index=4`的槽位已经有了数据,且`key`值不等于`ThreadLocal1`,所以需要继续往后迭代查找。 迭代到`index=5`的数据时,此时`Entry.key=null`,触发一次探测式数据回收操作,执行`expungeStaleEntry()`方法,执行完后,`index 5,8`的数据都会被回收,而`index 6,7`的数据都会前移,此时继续往后迭代,到`index = 6`的时候即找到了`key`值相等的`Entry`数据,如下图所示: @@ -724,9 +721,7 @@ private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) { } ``` - -### `ThreadLocalMap`过期key的启发式清理流程 - +### `ThreadLocalMap`过期 key 的启发式清理流程 上面多次提及到`ThreadLocalMap`过期可以的两种清理方式:**探测式清理(expungeStaleEntry())**、**启发式清理(cleanSomeSlots())** @@ -760,7 +755,7 @@ private boolean cleanSomeSlots(int i, int n) { 我们使用`ThreadLocal`的时候,在异步场景下是无法给子线程共享父线程中创建的线程副本数据的。 -为了解决这个问题,JDK中还有一个`InheritableThreadLocal`类,我们来看一个例子: +为了解决这个问题,JDK 中还有一个`InheritableThreadLocal`类,我们来看一个例子: ```java public class InheritableThreadLocalDemo { @@ -816,11 +811,11 @@ private void init(ThreadGroup g, Runnable target, String name, 我们现在项目中日志记录用的是`ELK+Logstash`,最后在`Kibana`中进行展示和检索。 -现在都是分布式系统统一对外提供服务,项目间调用的关系可以通过traceId来关联,但是不同项目之间如何传递`traceId`呢? +现在都是分布式系统统一对外提供服务,项目间调用的关系可以通过 `traceId` 来关联,但是不同项目之间如何传递 `traceId` 呢? -这里我们使用`org.slf4j.MDC`来实现此功能,内部就是通过`ThreadLocal`来实现的,具体实现如下: +这里我们使用 `org.slf4j.MDC` 来实现此功能,内部就是通过 `ThreadLocal` 来实现的,具体实现如下: -当前端发送请求到**服务A**时,**服务A**会生成一个类似`UUID`的`traceId`字符串,将此字符串放入当前线程的`ThreadLocal`中,在调用**服务B**的时候,将`traceId`写入到请求的`Header`中,**服务B**在接收请求时会先判断请求的`Header`中是否有`traceId`,如果存在则写入自己线程的`ThreadLocal`中。 +当前端发送请求到**服务 A**时,**服务 A**会生成一个类似`UUID`的`traceId`字符串,将此字符串放入当前线程的`ThreadLocal`中,在调用**服务 B**的时候,将`traceId`写入到请求的`Header`中,**服务 B**在接收请求时会先判断请求的`Header`中是否有`traceId`,如果存在则写入自己线程的`ThreadLocal`中。 ![](./images/thread-local/30.png) @@ -830,9 +825,10 @@ private void init(ThreadGroup g, Runnable target, String name, 针对于这些场景,我们都可以有相应的解决方案,如下所示 -#### Feign远程调用解决方案 +#### Feign 远程调用解决方案 **服务发送请求:** + ```java @Component @Slf4j @@ -849,6 +845,7 @@ public class FeignInvokeInterceptor implements RequestInterceptor { ``` **服务接收请求:** + ```java @Slf4j @Component @@ -876,13 +873,13 @@ public class LogInterceptor extends HandlerInterceptorAdapter { } ``` -#### 线程池异步调用,requestId传递 +#### 线程池异步调用,requestId 传递 因为`MDC`是基于`ThreadLocal`去实现的,异步过程中,子线程并没有办法获取到父线程`ThreadLocal`存储的数据,所以这里可以自定义线程池执行器,修改其中的`run()`方法: ```java public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { - + @Override public void execute(Runnable runnable) { Map context = MDC.getCopyOfContextMap(); @@ -903,11 +900,6 @@ public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { } ``` -#### 使用MQ发送消息给第三方系统 - -在MQ发送的消息体中自定义属性`requestId`,接收方消费消息后,自己解析`requestId`使用即可。 - - - - +#### 使用 MQ 发送消息给第三方系统 +在 MQ 发送的消息体中自定义属性`requestId`,接收方消费消息后,自己解析`requestId`使用即可。 From cfa58e4f68412ea48feef6bb3993fea00234e2b4 Mon Sep 17 00:00:00 2001 From: kaka2634 <996529090@qq.com> Date: Sat, 14 Aug 2021 17:53:39 +0800 Subject: [PATCH 07/20] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md=20-?= =?UTF-8?q?=20add=20chapter=20Queue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\351\235\242\350\257\225\351\242\230.md" | 95 +++++++++++++++---- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" index e604f81962c..c960924ee90 100644 --- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" +++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" @@ -310,9 +310,66 @@ Output: `TreeSet` 底层使用红黑树,能够按照添加元素的顺序进行遍历,排序的方式有自然排序和定制排序。 -## 1.4. Map 接口 +## 1.4 Collection 子接口之 Queue -### 1.4.1. HashMap 和 Hashtable 的区别 +### 1.4.1 Queue 与 Deque 的区别 + +`Queue` 是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 **先进先出(FIFO)** 规则。 + +`Queue` 扩展了 `Collection` 的接口,根据 **因为容量问题而导致操作失败后处理方式的不同** 可以分为两类方法: 一种在操作失败后会抛出异常,另一种则会返回特殊值。 + +| `Queue` 接口| 抛出异常 | 返回特殊值 | +| ------------ | --------- | ---------- | +| 插入队尾 | add(E e) | offer(E e) | +| 删除队首 | remove() | poll() | +| 查询队首元素 | element() | peek() | + +`Deque` 是双端队列,在队列的两端均可以插入或删除元素。 + +`Deque` 扩展了 `Queue` 的接口, 增加了在队首和队尾进行插入和删除的方法,同样根据失败后处理方式的不同分为两类: + +| `Deque`接口 | 抛出异常 | 返回特殊值 | +| ------------ | ------------- | --------------- | +| 插入队首 | addFirst(E e) | offerFirst(E e) | +| 插入队尾 | addLast(E e) | offerLast(E e) | +| 删除队首 | removeFirst() | pollFirst() | +| 删除队尾 | removeLast() | pollLast() | +| 查询队首元素 | getFirst() | peekFirst() | +| 查询队尾元素 | getLast() | peekLast() | + +事实上,`Deque` 还提供有 `push()` 和 `pop()` 等其他方法,用于模拟栈。 + + +### 1.4.2 ArrayDeque 与 LinkedList 的区别 + +`ArrayDeque` 和 `LinkedList` 都实现了`Deque`接口,两者都具有队列的功能,但两者有什么区别呢? + +- `ArrayDeque` 是基于可变长的数组和双指针来实现,而 `LinkedList` 则通过链表来实现。 + +- `ArrayDeque` 不支持存储 `NULL` 数据,但 `LinkedList` 支持。 + +- `ArrayDeque` 是在 JDK1.6 才被引入的,而`LinkedList` 早在 JDK1.2 时就已经存在。 + +- `ArrayDeque` 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1)。虽然 `LinkedList` 不需要扩容,但是每次插入数据时均需要申请新的堆空间,均摊性能相比更慢。 + +从性能的角度上,选用 `ArrayDeque` 去实现队列要比 `LinkedList` 更好。此外,`ArrayDeque` 也可以用于实现栈。 + +### 1.4.3 说一说 PriorityQueue + +`PriorityQueue` 是在 JDK1.5 中被引入的, 其与 `Queue` 的区别在于元素出队顺序是与优先级相关的,即总是优先级最高的元素先出队。 + +这里列举其相关的一些要点: + +- `PriorityQueue` 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据 +- `PriorityQueue` 通过堆元素的上浮和下沉,实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。 +- `PriorityQueue` 是非线程安全的,且不支持存储 `NULL` 和 `non-comparable` 的对象。 +- `PriorityQueue` 默认是小顶堆,可以接收一个`Comparator`作为构造参数来比较队列中元素的优先级。 + +`PriorityQueue` 在面试中可能更多的会出现在手撕算法的时候,典型例题包括堆排序、求第K大的数、带权图的遍历等,所以需要学会熟练使用才行。 + +## 1.5. Map 接口 + +### 1.5.1. HashMap 和 Hashtable 的区别 1. **线程是否安全:** `HashMap` 是非线程安全的,`HashTable` 是线程安全的,因为 `HashTable` 内部的方法基本都经过`synchronized` 修饰。(如果你要保证线程安全的话就使用 `ConcurrentHashMap` 吧!); 2. **效率:** 因为线程安全的问题,`HashMap` 要比 `HashTable` 效率高一点。另外,`HashTable` 基本被淘汰,不要在代码中使用它; @@ -357,7 +414,7 @@ Output: } ``` -### 1.4.2. HashMap 和 HashSet 区别 +### 1.5.2. HashMap 和 HashSet 区别 如果你看过 `HashSet` 源码的话就应该知道:`HashSet` 底层就是基于 `HashMap` 实现的。(`HashSet` 的源码非常非常少,因为除了 `clone()`、`writeObject()`、`readObject()`是 `HashSet` 自己不得不实现之外,其他方法都是直接调用 `HashMap` 中的方法。 @@ -368,7 +425,7 @@ Output: | 调用 `put()`向 map 中添加元素 | 调用 `add()`方法向 `Set` 中添加元素 | | `HashMap` 使用键(Key)计算 `hashcode` | `HashSet` 使用成员对象来计算 `hashcode` 值,对于两个对象来说 `hashcode` 可能相同,所以`equals()`方法用来判断对象的相等性 | -### 1.4.3. HashMap 和 TreeMap 区别 +### 1.5.3. HashMap 和 TreeMap 区别 `TreeMap` 和`HashMap` 都继承自`AbstractMap` ,但是需要注意的是`TreeMap`它还实现了`NavigableMap`接口和`SortedMap` 接口。 @@ -436,7 +493,7 @@ TreeMap treeMap = new TreeMap<>((person1, person2) -> { **综上,相比于`HashMap`来说 `TreeMap` 主要多了对集合中的元素根据键排序的能力以及对集合内元素的搜索的能力。** -### 1.4.4. HashSet 如何检查重复 +### 1.5.4. HashSet 如何检查重复 以下内容摘自我的 Java 启蒙书《Head first java》第二版: @@ -479,9 +536,9 @@ final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 对于引用类型(包括包装类型)来说,equals 如果没有被重写,对比它们的地址是否相等;如果 equals()方法被重写(例如 String),则比较的是地址里的内容。 -### 1.4.5. HashMap 的底层实现 +### 1.5.5. HashMap 的底层实现 -#### 1.4.5.1. JDK1.8 之前 +#### 1.5.5.1. JDK1.8 之前 JDK1.8 之前 `HashMap` 底层是 **数组和链表** 结合在一起使用也就是 **链表散列**。**HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。** @@ -520,7 +577,7 @@ static int hash(int h) { ![jdk1.8之前的内部结构-HashMap](images/jdk1.8之前的内部结构-HashMap.png) -#### 1.4.5.2. JDK1.8 之后 +#### 1.5.5.2. JDK1.8 之后 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。 @@ -528,7 +585,7 @@ static int hash(int h) { > TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。 -### 1.4.6. HashMap 的长度为什么是 2 的幂次方 +### 1.5.6. HashMap 的长度为什么是 2 的幂次方 为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。我们上面也讲到了过了,Hash 值的范围值-2147483648 到 2147483647,前后加起来大概 40 亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是一个 40 亿长度的数组,内存是放不下的。所以这个散列值是不能直接拿来用的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ `(n - 1) & hash`”。(n 代表数组长度)。这也就解释了 HashMap 的长度为什么是 2 的幂次方。 @@ -536,17 +593,17 @@ static int hash(int h) { 我们首先可能会想到采用%取余的操作来实现。但是,重点来了:**“取余(%)操作中如果除数是 2 的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是 2 的 n 次方;)。”** 并且 **采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是 2 的幂次方。** -### 1.4.7. HashMap 多线程操作导致死循环问题 +### 1.5.7. HashMap 多线程操作导致死循环问题 主要原因在于并发下的 Rehash 会造成元素之间会形成一个循环链表。不过,jdk 1.8 后解决了这个问题,但是还是不建议在多线程下使用 HashMap,因为多线程下使用 HashMap 还是会存在其他问题比如数据丢失。并发环境下推荐使用 ConcurrentHashMap 。 详情请查看: -### 1.4.8. HashMap 有哪几种常见的遍历方式? +### 1.5.8. HashMap 有哪几种常见的遍历方式? [HashMap 的 7 种遍历方式与性能分析!](https://mp.weixin.qq.com/s/zQBN3UvJDhRTKP6SzcZFKw) -### 1.4.9. ConcurrentHashMap 和 Hashtable 的区别 +### 1.5.9. ConcurrentHashMap 和 Hashtable 的区别 `ConcurrentHashMap` 和 `Hashtable` 的区别主要体现在实现线程安全的方式上不同。 @@ -573,9 +630,9 @@ static int hash(int h) { JDK1.8 的 `ConcurrentHashMap` 不在是 **Segment 数组 + HashEntry 数组 + 链表**,而是 **Node 数组 + 链表 / 红黑树**。不过,Node 只能用于链表的情况,红黑树的情况需要使用 **`TreeNode`**。当冲突链表达到一定长度时,链表会转换成红黑树。 -### 1.4.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现 +### 1.5.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现 -#### 1.4.10.1. JDK1.7(上面有示意图) +#### 1.5.10.1. JDK1.7(上面有示意图) 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 @@ -590,13 +647,13 @@ static class Segment extends ReentrantLock implements Serializable { 一个 `ConcurrentHashMap` 里包含一个 `Segment` 数组。`Segment` 的结构和 `HashMap` 类似,是一种数组和链表结构,一个 `Segment` 包含一个 `HashEntry` 数组,每个 `HashEntry` 是一个链表结构的元素,每个 `Segment` 守护着一个 `HashEntry` 数组里的元素,当对 `HashEntry` 数组的数据进行修改时,必须首先获得对应的 `Segment` 的锁。 -#### 1.4.10.2. JDK1.8 (上面有示意图) +#### 1.5.10.2. JDK1.8 (上面有示意图) `ConcurrentHashMap` 取消了 `Segment` 分段锁,采用 CAS 和 `synchronized` 来保证并发安全。数据结构跟 HashMap1.8 的结构类似,数组+链表/红黑二叉树。Java 8 在链表长度超过一定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红黑树(寻址时间复杂度为 O(log(N))) `synchronized` 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发,效率又提升 N 倍。 -## 1.5. Collections 工具类 +## 1.6. Collections 工具类 Collections 工具类常用方法: @@ -604,7 +661,7 @@ Collections 工具类常用方法: 2. 查找,替换操作 3. 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合) -### 1.5.1. 排序操作 +### 1.6.1. 排序操作 ```java void reverse(List list)//反转 @@ -615,7 +672,7 @@ void swap(List list, int i , int j)//交换两个索引位置的元素 void rotate(List list, int distance)//旋转。当distance为正数时,将list后distance个元素整体移到前面。当distance为负数时,将 list的前distance个元素整体移到后面 ``` -### 1.5.2. 查找,替换操作 +### 1.6.2. 查找,替换操作 ```java int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的 @@ -627,7 +684,7 @@ int indexOfSubList(List list, List target)//统计target在list中第一次出 boolean replaceAll(List list, Object oldVal, Object newVal)//用新元素替换旧元素 ``` -### 1.5.3. 同步控制 +### 1.6.3. 同步控制 `Collections` 提供了多个`synchronizedXxx()`方法·,该方法可以将指定集合包装成线程同步的集合,从而解决多线程并发访问集合时的线程安全问题。 From 04e7b5892830c62582c9cb01e9909e6b507e8d1d Mon Sep 17 00:00:00 2001 From: kaka2634 <996529090@qq.com> Date: Sat, 14 Aug 2021 18:47:40 +0800 Subject: [PATCH 08/20] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\351\235\242\350\257\225\351\242\230.md" | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" index c960924ee90..67953e38a4b 100644 --- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" +++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" @@ -3,11 +3,12 @@ - [1. 剖析面试最常见问题之 Java 集合框架](#1-剖析面试最常见问题之-java-集合框架) - [1.1. 集合概述](#11-集合概述) - [1.1.1. Java 集合概览](#111-java-集合概览) - - [1.1.2. 说说 List,Set,Map 三者的区别?](#112-说说-listsetmap-三者的区别) + - [1.1.2. 说说 List, Set, Queue, Map 四者的区别?](#112-说说-list-set-queue-map-四者的区别) - [1.1.3. 集合框架底层数据结构总结](#113-集合框架底层数据结构总结) - [1.1.3.1. List](#1131-list) - [1.1.3.2. Set](#1132-set) - - [1.1.3.3. Map](#1133-map) + - [1.1.3.3 Queue](#1133-queue) + - [1.1.3.4. Map](#1134-map) - [1.1.4. 如何选用集合?](#114-如何选用集合) - [1.1.5. 为什么要使用集合?](#115-为什么要使用集合) - [1.2. Collection 子接口之 List](#12-collection-子接口之-list) @@ -22,25 +23,29 @@ - [1.3.1.2. 重写 compareTo 方法实现按年龄来排序](#1312-重写-compareto-方法实现按年龄来排序) - [1.3.2. 无序性和不可重复性的含义是什么](#132-无序性和不可重复性的含义是什么) - [1.3.3. 比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同](#133-比较-hashsetlinkedhashset-和-treeset-三者的异同) - - [1.4. Map 接口](#14-map-接口) - - [1.4.1. HashMap 和 Hashtable 的区别](#141-hashmap-和-hashtable-的区别) - - [1.4.2. HashMap 和 HashSet 区别](#142-hashmap-和-hashset-区别) - - [1.4.3. HashMap 和 TreeMap 区别](#143-hashmap-和-treemap-区别) - - [1.4.4. HashSet 如何检查重复](#144-hashset-如何检查重复) - - [1.4.5. HashMap 的底层实现](#145-hashmap-的底层实现) - - [1.4.5.1. JDK1.8 之前](#1451-jdk18-之前) - - [1.4.5.2. JDK1.8 之后](#1452-jdk18-之后) - - [1.4.6. HashMap 的长度为什么是 2 的幂次方](#146-hashmap-的长度为什么是-2-的幂次方) - - [1.4.7. HashMap 多线程操作导致死循环问题](#147-hashmap-多线程操作导致死循环问题) - - [1.4.8. HashMap 有哪几种常见的遍历方式?](#148-hashmap-有哪几种常见的遍历方式) - - [1.4.9. ConcurrentHashMap 和 Hashtable 的区别](#149-concurrenthashmap-和-hashtable-的区别) - - [1.4.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](#1410-concurrenthashmap-线程安全的具体实现方式底层具体实现) - - [1.4.10.1. JDK1.7(上面有示意图)](#14101-jdk17上面有示意图) - - [1.4.10.2. JDK1.8 (上面有示意图)](#14102-jdk18-上面有示意图) - - [1.5. Collections 工具类](#15-collections-工具类) - - [1.5.1. 排序操作](#151-排序操作) - - [1.5.2. 查找,替换操作](#152-查找替换操作) - - [1.5.3. 同步控制](#153-同步控制) + - [1.4 Collection 子接口之 Queue](#14-collection-子接口之-queue) + - [1.4.1 Queue 与 Deque 的区别](#141-queue-与-deque-的区别) + - [1.4.2 ArrayDeque 与 LinkedList 的区别](#142-arraydeque-与-linkedlist-的区别) + - [1.4.3 说一说 PriorityQueue](#143-说一说-priorityqueue) + - [1.5. Map 接口](#15-map-接口) + - [1.5.1. HashMap 和 Hashtable 的区别](#151-hashmap-和-hashtable-的区别) + - [1.5.2. HashMap 和 HashSet 区别](#152-hashmap-和-hashset-区别) + - [1.5.3. HashMap 和 TreeMap 区别](#153-hashmap-和-treemap-区别) + - [1.5.4. HashSet 如何检查重复](#154-hashset-如何检查重复) + - [1.5.5. HashMap 的底层实现](#155-hashmap-的底层实现) + - [1.5.5.1. JDK1.8 之前](#1551-jdk18-之前) + - [1.5.5.2. JDK1.8 之后](#1552-jdk18-之后) + - [1.5.6. HashMap 的长度为什么是 2 的幂次方](#156-hashmap-的长度为什么是-2-的幂次方) + - [1.5.7. HashMap 多线程操作导致死循环问题](#157-hashmap-多线程操作导致死循环问题) + - [1.5.8. HashMap 有哪几种常见的遍历方式?](#158-hashmap-有哪几种常见的遍历方式) + - [1.5.9. ConcurrentHashMap 和 Hashtable 的区别](#159-concurrenthashmap-和-hashtable-的区别) + - [1.5.10. ConcurrentHashMap 线程安全的具体实现方式/底层具体实现](#1510-concurrenthashmap-线程安全的具体实现方式底层具体实现) + - [1.5.10.1. JDK1.7(上面有示意图)](#15101-jdk17上面有示意图) + - [1.5.10.2. JDK1.8 (上面有示意图)](#15102-jdk18-上面有示意图) + - [1.6. Collections 工具类](#16-collections-工具类) + - [1.6.1. 排序操作](#161-排序操作) + - [1.6.2. 查找,替换操作](#162-查找替换操作) + - [1.6.3. 同步控制](#163-同步控制) From fb609a83ed1804ed6467305c69811e0e0cc6ea07 Mon Sep 17 00:00:00 2001 From: kaka2634 <996529090@qq.com> Date: Sat, 14 Aug 2021 19:03:14 +0800 Subject: [PATCH 09/20] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\247\201\351\235\242\350\257\225\351\242\230.md" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" index 67953e38a4b..ce99f80418e 100644 --- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" +++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" @@ -333,7 +333,7 @@ Output: `Deque` 扩展了 `Queue` 的接口, 增加了在队首和队尾进行插入和删除的方法,同样根据失败后处理方式的不同分为两类: -| `Deque`接口 | 抛出异常 | 返回特殊值 | +| `Deque` 接口 | 抛出异常 | 返回特殊值 | | ------------ | ------------- | --------------- | | 插入队首 | addFirst(E e) | offerFirst(E e) | | 插入队尾 | addLast(E e) | offerLast(E e) | @@ -342,12 +342,12 @@ Output: | 查询队首元素 | getFirst() | peekFirst() | | 查询队尾元素 | getLast() | peekLast() | -事实上,`Deque` 还提供有 `push()` 和 `pop()` 等其他方法,用于模拟栈。 +事实上,`Deque` 还提供有 `push()` 和 `pop()` 等其他方法,可用于模拟栈。 ### 1.4.2 ArrayDeque 与 LinkedList 的区别 -`ArrayDeque` 和 `LinkedList` 都实现了`Deque`接口,两者都具有队列的功能,但两者有什么区别呢? +`ArrayDeque` 和 `LinkedList` 都实现了 `Deque` 接口,两者都具有队列的功能,但两者有什么区别呢? - `ArrayDeque` 是基于可变长的数组和双指针来实现,而 `LinkedList` 则通过链表来实现。 @@ -357,7 +357,7 @@ Output: - `ArrayDeque` 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1)。虽然 `LinkedList` 不需要扩容,但是每次插入数据时均需要申请新的堆空间,均摊性能相比更慢。 -从性能的角度上,选用 `ArrayDeque` 去实现队列要比 `LinkedList` 更好。此外,`ArrayDeque` 也可以用于实现栈。 +从性能的角度上,选用 `ArrayDeque` 来实现队列要比 `LinkedList` 更好。此外,`ArrayDeque` 也可以用于实现栈。 ### 1.4.3 说一说 PriorityQueue @@ -368,9 +368,9 @@ Output: - `PriorityQueue` 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据 - `PriorityQueue` 通过堆元素的上浮和下沉,实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。 - `PriorityQueue` 是非线程安全的,且不支持存储 `NULL` 和 `non-comparable` 的对象。 -- `PriorityQueue` 默认是小顶堆,可以接收一个`Comparator`作为构造参数来比较队列中元素的优先级。 +- `PriorityQueue` 默认是小顶堆,但可以接收一个 `Comparator` 作为构造参数,从而来自定义元素优先级的先后。 -`PriorityQueue` 在面试中可能更多的会出现在手撕算法的时候,典型例题包括堆排序、求第K大的数、带权图的遍历等,所以需要学会熟练使用才行。 +`PriorityQueue` 在面试中可能更多的会出现在手撕算法的时候,典型例题包括堆排序、求第K大的数、带权图的遍历等,所以需要会熟练使用才行。 ## 1.5. Map 接口 From d5d61b303c341bcf40ec48e0636000d02494b272 Mon Sep 17 00:00:00 2001 From: guide Date: Sun, 15 Aug 2021 08:54:19 +0800 Subject: [PATCH 10/20] =?UTF-8?q?[feat]MySQL=E4=B8=89=E5=A4=A7=E6=97=A5?= =?UTF-8?q?=E5=BF=97(binlog=E3=80=81redo=20log=E5=92=8Cundo=20log)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +- ...3\200\201redo log\345\222\214undo log).md" | 280 ++++++++++++++++++ 2 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 "docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md" diff --git a/README.md b/README.md index 7cf58b258f0..eca328cc313 100644 --- a/README.md +++ b/README.md @@ -147,9 +147,10 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle 1. [MySQL数据库索引总结](docs/database/mysql/MySQL数据库索引.md) 2. [事务隔离级别(图文详解)](docs/database/mysql/事务隔离级别(图文详解).md) -3. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/InnoDB对MVCC的实现.md) -4. [一条 SQL 语句在 MySQL 中如何执行的](docs/database/mysql/一条sql语句在mysql中如何执行的.md) -5. [关于数据库中如何存储时间的一点思考](docs/database/mysql/关于数据库存储时间的一点思考.md) +3. [MySQL三大日志(binlog、redo log和undo log)详解](docs/database/mysql/MySQL三大日志(binlog、redo log和undo log).md) +4. [InnoDB存储引擎对MVCC的实现](docs/database/mysql/InnoDB对MVCC的实现.md) +5. [一条 SQL 语句在 MySQL 中如何执行的](docs/database/mysql/一条sql语句在mysql中如何执行的.md) +6. [关于数据库中如何存储时间的一点思考](docs/database/mysql/关于数据库存储时间的一点思考.md) ### Redis diff --git "a/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md" "b/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md" new file mode 100644 index 00000000000..616fab71874 --- /dev/null +++ "b/docs/database/mysql/MySQL\344\270\211\345\244\247\346\227\245\345\277\227(binlog\343\200\201redo log\345\222\214undo log).md" @@ -0,0 +1,280 @@ +> 本文来自公号程序猿阿星投稿,JavaGuide 对其做了补充完善。 + +## 前言 + +`MySQL` 日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志 `binlog`(归档日志)和事务日志 `redo log`(重做日志)和 `undo log`(回滚日志)。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/01.png) + +今天就来聊聊 `redo log`(重做日志)、`binlog`(归档日志)、两阶段提交、`undo log` (回滚日志)。 + +## redo log + +`redo log`(重做日志)是`InnoDB`存储引擎独有的,它让`MySQL`拥有了崩溃恢复能力。 + +比如 `MySQL` 实例挂了或宕机了,重启时,`InnoDB`存储引擎会使用`redo log`恢复数据,保证数据的持久性与完整性。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/02.png) + +`MySQL` 中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 `Buffer Pool` 中。 + +后续的查询都是先从 `Buffer Pool` 中找,没有命中再去硬盘加载,减少硬盘 `IO` 开销,提升性能。 + +更新表数据的时候,也是如此,发现 `Buffer Pool` 里存在要更新的数据,就直接在 `Buffer Pool` 里更新。 + +然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(`redo log buffer`)里,接着刷盘到 `redo log` 文件里。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/03.png) + +理想情况,事务一提交就会进行刷盘操作,但实际上,刷盘的时机是根据策略来进行的。 + +> 小贴士:每条 redo 记录由“表空间号+数据页号+偏移量+修改数据长度+具体修改的数据”组成 + +### 刷盘时机 + +`InnoDB` 存储引擎为 `redo log` 的刷盘策略提供了 `innodb_flush_log_at_trx_commit` 参数,它支持三种策略: + +- **0** :设置为 0 的时候,表示每次事务提交时不进行刷盘操作 +- **1** :设置为 1 的时候,表示每次事务提交时都将进行刷盘操作(默认值) +- **2** :设置为 2 的时候,表示每次事务提交时都只把 redo log buffer 内容写入 page cache + +`innodb_flush_log_at_trx_commit` 参数默认为 1 ,也就是说当事务提交时会调用 `fsync` 对 redo log 进行刷盘 + +另外,`InnoDB` 存储引擎有一个后台线程,每隔`1` 秒,就会把 `redo log buffer` 中的内容写到文件系统缓存(`page cache`),然后调用 `fsync` 刷盘。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/04.png) + +也就是说,一个没有提交事务的 `redo log` 记录,也可能会刷盘。 + +**为什么呢?** + +因为在事务执行过程 `redo log` 记录是会写入`redo log buffer` 中,这些 `redo log` 记录会被后台线程刷盘。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/05.png) + +除了后台线程每秒`1`次的轮询操作,还有一种情况,当 `redo log buffer` 占用的空间即将达到 `innodb_log_buffer_size` 一半的时候,后台线程会主动刷盘。 + +下面是不同刷盘策略的流程图。 + +#### innodb_flush_log_at_trx_commit=0 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/06.png) + +为`0`时,如果`MySQL`挂了或宕机可能会有`1`秒数据的丢失。 + +#### innodb_flush_log_at_trx_commit=1 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/07.png) + +为`1`时, 只要事务提交成功,`redo log`记录就一定在硬盘里,不会有任何数据丢失。 + +如果事务执行期间`MySQL`挂了或宕机,这部分日志丢了,但是事务并没有提交,所以日志丢了也不会有损失。 + +#### innodb_flush_log_at_trx_commit=2 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/09.png) + +为`2`时, 只要事务提交成功,`redo log buffer`中的内容只写入文件系统缓存(`page cache`)。 + +如果仅仅只是`MySQL`挂了不会有任何数据丢失,但是宕机可能会有`1`秒数据的丢失。 + +### 日志文件组 + +硬盘上存储的 `redo log` 日志文件不只一个,而是以一个**日志文件组**的形式出现的,每个的`redo`日志文件大小都是一样的。 + +比如可以配置为一组`4`个文件,每个文件的大小是 `1GB`,整个 `redo log` 日志文件组可以记录`4G`的内容。 + +它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/10.png) + +在个**日志文件组**中还有两个重要的属性,分别是 `write pos、checkpoint` + +- **write pos** 是当前记录的位置,一边写一边后移 +- **checkpoint** 是当前要擦除的位置,也是往后推移 + +每次刷盘 `redo log` 记录到**日志文件组**中,`write pos` 位置就会后移更新。 + +每次 `MySQL` 加载**日志文件组**恢复数据时,会清空加载过的 `redo log` 记录,并把 `checkpoint` 后移更新。 + +`write pos` 和 `checkpoint` 之间的还空着的部分可以用来写入新的 `redo log` 记录。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/11.png) + +如果 `write pos` 追上 `checkpoint` ,表示**日志文件组**满了,这时候不能再写入新的 `redo log` 记录,`MySQL` 得停下来,清空一些记录,把 `checkpoint` 推进一下。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/03/12.png) + +### redo log 小结 + +相信大家都知道 `redo log` 的作用和它的刷盘时机、存储形式。 + +现在我们来思考一个问题: **只要每次把修改后的数据页直接刷盘不就好了,还有 `redo log` 什么事?** + +它们不都是刷盘么?差别在哪里? + +```java +1 Byte = 8bit +1 KB = 1024 Byte +1 MB = 1024 KB +1 GB = 1024 MB +1 TB = 1024 GB +``` + +实际上,数据页大小是`16KB`,刷盘比较耗时,可能就修改了数据页里的几 `Byte` 数据,有必要把完整的数据页刷盘吗? + +而且数据页刷盘是随机写,因为一个数据页对应的位置可能在硬盘文件的随机位置,所以性能是很差。 + +如果是写 `redo log`,一行记录可能就占几十 `Byte`,只包含表空间号、数据页号、磁盘文件偏移 +量、更新值,再加上是顺序写,所以刷盘速度很快。 + +所以用 `redo log` 形式记录修改内容,性能会远远超过刷数据页的方式,这也让数据库的并发能力更强。 + +> 其实内存的数据页在一定时机也会刷盘,我们把这称为页合并,讲 `Buffer Pool`的时候会对这块细说 + +## binlog + +`redo log` 它是物理日志,记录内容是“在某个数据页上做了什么修改”,属于 `InnoDB` 存储引擎。 + +而 `binlog` 是逻辑日志,记录内容是语句的原始逻辑,类似于“给 ID=2 这一行的 c 字段加 1”,属于`MySQL Server` 层。 + +不管用什么存储引擎,只要发生了表数据更新,都会产生 `binlog` 日志。 + +那 `binlog` 到底是用来干嘛的? + +可以说`MySQL`数据库的**数据备份、主备、主主、主从**都离不开`binlog`,需要依靠`binlog`来同步数据,保证数据一致性。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/01.png) + +`binlog`会记录所有涉及更新数据的逻辑操作,并且是顺序写。 + +### 记录格式 + +`binlog` 日志有三种格式,可以通过`binlog_format`参数指定。 + +- **statement** +- **row** +- **mixed** + +指定`statement`,记录的内容是`SQL`语句原文,比如执行一条`update T set update_time=now() where id=1`,记录的内容如下。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/02.png) + +同步数据时,会执行记录的`SQL`语句,但是有个问题,`update_time=now()`这里会获取当前系统时间,直接执行会导致与原库的数据不一致。 + +为了解决这种问题,我们需要指定为`row`,记录的内容不再是简单的`SQL`语句了,还包含操作的具体数据,记录内容如下。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/03.png) + +`row`格式记录的内容看不到详细信息,要通过`mysqlbinlog`工具解析出来。 + +`update_time=now()`变成了具体的时间`update_time=1627112756247`,条件后面的@1、@2、@3 都是该行数据第 1 个~3 个字段的原始值(**假设这张表只有 3 个字段**)。 + +这样就能保证同步数据的一致性,通常情况下都是指定为`row`,这样可以为数据库的恢复与同步带来更好的可靠性。 + +但是这种格式,需要更大的容量来记录,比较占用空间,恢复与同步时会更消耗`IO`资源,影响执行速度。 + +所以就有了一种折中的方案,指定为`mixed`,记录的内容是前两者的混合。 + +`MySQL`会判断这条`SQL`语句是否可能引起数据不一致,如果是,就用`row`格式,否则就用`statement`格式。 + +### 写入机制 + +`binlog`的写入时机也非常简单,事务执行过程中,先把日志写到`binlog cache`,事务提交的时候,再把`binlog cache`写到`binlog`文件中。 + +因为一个事务的`binlog`不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为`binlog cache`。 + +我们可以通过`binlog_cache_size`参数控制单个线程 binlog cache 大小,如果存储内容超过了这个参数,就要暂存到磁盘(`Swap`)。 + +`binlog`日志刷盘流程如下 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/04.png) + +- **上图的 write,是指把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快** +- **上图的 fsync,才是将数据持久化到磁盘的操作** + +`write`和`fsync`的时机,可以由参数`sync_binlog`控制,默认是`0`。 + +为`0`的时候,表示每次提交事务都只`write`,由系统自行判断什么时候执行`fsync`。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/05.png) + +虽然性能得到提升,但是机器宕机,`page cache`里面的 binglog 会丢失。 + +为了安全起见,可以设置为`1`,表示每次提交事务都会执行`fsync`,就如同**binlog 日志刷盘流程**一样。 + +最后还有一种折中方式,可以设置为`N(N>1)`,表示每次提交事务都`write`,但累积`N`个事务后才`fsync`。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/04/06.png) + +在出现`IO`瓶颈的场景里,将`sync_binlog`设置成一个比较大的值,可以提升性能。 + +同样的,如果机器宕机,会丢失最近`N`个事务的`binlog`日志。 + +## 两阶段提交 + +`redo log`(重做日志)让`InnoDB`存储引擎拥有了崩溃恢复能力。 + +`binlog`(归档日志)保证了`MySQL`集群架构的数据一致性。 + +虽然它们都属于持久化的保证,但是则重点不同。 + +在执行更新语句过程,会记录`redo log`与`binlog`两块日志,以基本的事务为单位,`redo log`在事务执行过程中可以不断写入,而`binlog`只有在提交事务时才写入,所以`redo log`与`binlog`的写入时机不一样。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/01.png) + +回到正题,`redo log`与`binlog`两份日志之间的逻辑不一致,会出现什么问题? + +我们以`update`语句为例,假设`id=2`的记录,字段`c`值是`0`,把字段`c`值更新成`1`,`SQL`语句为`update T set c=1 where id=2`。 + +假设执行过程中写完`redo log`日志后,`binlog`日志写期间发生了异常,会出现什么情况呢? + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/02.png) + +由于`binlog`没写完就异常,这时候`binlog`里面没有对应的修改记录。因此,之后用`binlog`日志恢复数据时,就会少这一次更新,恢复出来的这一行`c`值是`0`,而原库因为`redo log`日志恢复,这一行`c`值是`1`,最终数据不一致。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/03.png) + +为了解决两份日志之间的逻辑一致问题,`InnoDB`存储引擎使用**两阶段提交**方案。 + +原理很简单,将`redo log`的写入拆成了两个步骤`prepare`和`commit`,这就是**两阶段提交**。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/04.png) + +使用**两阶段提交**后,写入`binlog`时发生异常也不会有影响,因为`MySQL`根据`redo log`日志恢复数据时,发现`redo log`还处于`prepare`阶段,并且没有对应`binlog`日志,就会回滚该事务。 + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/05.png) + +再看一个场景,`redo log`设置`commit`阶段发生异常,那会不会回滚事务呢? + +![](https://cdn.jsdelivr.net/gh/18702524676/CND5/image/mysql/05/06.png) + +并不会回滚事务,它会执行上图框住的逻辑,虽然`redo log`是处于`prepare`阶段,但是能通过事务`id`找到对应的`binlog`日志,所以`MySQL`认为是完整的,就会提交事务恢复数据。 + +## undo log + +> 这部分内容为 JavaGuide 的补充: + +我们知道如果想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行**回滚**,在 MySQL 中,恢复机制是通过 **回滚日志(undo log)** 实现的,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,我们直接利用 **回滚日志** 中的信息将数据回滚到修改之前的样子即可!并且,回滚日志会先于数据持久化到磁盘上。这样就保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务。 + +另外,`MVCC` 的实现依赖于:**隐藏字段、Read View、undo log**。在内部实现中,`InnoDB` 通过数据行的 `DB_TRX_ID` 和 `Read View` 来判断数据的可见性,如不可见,则通过数据行的 `DB_ROLL_PTR` 找到 `undo log` 中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 `Read View` 之前已经提交的修改和该事务本身做的修改 + +## 总结 + +> 这部分内容为 JavaGuide 的补充: + +MySQL InnoDB 引擎使用 **redo log(重做日志)** 保证事务的**持久性**,使用 **undo log(回滚日志)** 来保证事务的**原子性**。 + +`MySQL`数据库的**数据备份、主备、主主、主从**都离不开`binlog`,需要依靠`binlog`来同步数据,保证数据一致性。 + +## 站在巨人的肩膀上 + +- 《MySQL 实战 45 讲》 +- 《从零开始带你成为 MySQL 实战优化高手》 +- 《MySQL 是怎样运行的:从根儿上理解 MySQL》 +- 《MySQL 技术 Innodb 存储引擎》 + +## MySQL 好文推荐 + +- [CURD 这么多年,你有了解过 MySQL 的架构设计吗?](https://mp.weixin.qq.com/s/R-1km7r0z3oWfwYQV8iiqA) +- [浅谈 MySQL InnoDB 的内存组件](https://mp.weixin.qq.com/s/7Kab4IQsNcU_bZdbv_MuOg) \ No newline at end of file From b46a3c382a6af7fcb33f836f122e72aa4c55edd8 Mon Sep 17 00:00:00 2001 From: guide Date: Mon, 16 Aug 2021 14:42:44 +0800 Subject: [PATCH 11/20] =?UTF-8?q?[feat]java9=20=E6=96=B0=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\346\226\260\347\211\271\346\200\247.md" | 231 ++++++++++++++---- 1 file changed, 181 insertions(+), 50 deletions(-) diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" index 2d56e512255..dc1d4318f74 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" @@ -1,32 +1,161 @@ -大家好,我是Guide哥!这篇文章来自读者的投稿,经过了两次较大的改动,两周的完善终于完成。Java 8新特性见这里:[Java8新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。 +Java 8 新特性见这里:[Java8 新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。 -*Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!* +_Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!_ ## Java9 -发布于 2017 年 9 月 21 日 。作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如集合、Stream 流 +发布于 2017 年 9 月 21 日 。作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如集合、Stream 流 ### Java 平台模块系统 -Java 平台模块系统,也就是 Project Jigsaw,把模块化开发实践引入到了 Java 平台中。在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。 +Java 平台模块系统是[Jigsaw Project](https://openjdk.java.net/projects/jigsaw/)的一部分,把模块化开发实践引入到了 Java 平台中,可以让我们的代码可重用性更好! -Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 module-info.class 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。 +什么是模块系统?官方的定义是:A uniquely named, reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor. + +简单来说,你可以将一个模块看作是一组唯一命名、可重用的包、资源和模块描述文件(module-info.java)。 + +任意一个 jar 文件,只要加上一个 模块描述文件(module-info.java),就可以升级为一个模块。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/module-structure.png) + +在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。 + +我们可以通过 exports 关键词精准控制哪些类可以对外开放使用,哪些类只能内部使用。 + +```java +module my.module { + //exports 公开指定包的所有公共成员 + exports com.my.package.name; +} + +module my.module { + //exports…to 限制访问的成员范围 + export com.my.package.name to com.specific.package; +} +``` + +Java 9 模块的重要特征是在其工件(artifact)的根目录中包含了一个描述模块的 `module-info.java` 文 件。 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。 + +想要深入了解 Java 9 的模块化,参见: + +- [Project Jigsaw: Module System Quick-Start Guide](https://openjdk.java.net/projects/jigsaw/quick-start) +- [Java 9 Modules: part 1](https://stacktraceguru.com/java9/module-introduction) ### Jshell jshell 是 Java 9 新增的一个实用工具。为 Java 提供了类似于 Python 的实时命令行交互工具。 -在 Jshell 中可以直接输入表达式并查看其执行结果 +在 Jshell 中可以直接输入表达式并查看其执行结果。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/image-20210816083417616.png) -### 集合、Stream 和 Optional +### 集合增强 -- 增加 了 `List.of()`、`Set.of()`、`Map.of()` 和 `Map.ofEntries()`等工厂方法来创建不可变集合,比如`List.of("Java", "C++");`、`Map.of("Java", 1, "C++", 2)`;(这部分内容有点参考 Guava 的味道) -- `Stream` 中增加了新的方法 `ofNullable`、`dropWhile`、`takeWhile` 和 `iterate` 方法。`Collectors` 中增加了新的方法 `filtering` 和 `flatMapping` -- `Optional` 类中新增了 `ifPresentOrElse`、`or` 和 `stream` 等方法 +增加 了 `List.of()`、`Set.of()`、`Map.of()` 和 `Map.ofEntries()`等工厂方法来创建不可变集合(这部分内容有点参考 Guava 的味道) + +```java +List.of("Java", "C++"); +Set.of("Java", "C++"); +Map.of("Java", 1, "C++", 2)`; +``` + +`Collectors` 中增加了新的方法 `filtering()` 和 `flatMapping()`。 + +`Collectors` 的 `filtering()` 方法类似于 `Stream` 类的 `filter()` 方法,都是用于过滤元素。 + +> Java 8 为 `Collectors` 类引入了 `groupingBy` 操作,用于根据特定的属性将对象分组。 + +```java +List list = List.of("x","www", "yy", "zz"); +Map> result = list.stream() + .collect(Collectors.groupingBy(String::length, + Collectors.filtering(s -> !s.contains("z"), + Collectors.toList()))); + +System.out.println(result); // {1=[x], 2=[yy], 3=[www]} +``` + +### Stream & Optional 增强 + +`Stream` 中增加了新的方法 `ofNullable()`、`dropWhile()`、`takeWhile()` 以及 `iterate()` 方法的重载方法。 + +Java 9 中的 `ofNullable()` 方 法允许我们创建一个单元素的 `Stream`,可以包含一个非空元素,也可以创建一个空 `Stream`。 而在 Java 8 中则不可以创建空的 `Stream` 。 + +```java +Stream stringStream = Stream.ofNullable("Java"); +System.out.println(stringStream.count());// 1 +Stream nullStream = Stream.ofNullable(null); +System.out.println(nullStream.count());//0 +``` + +`takeWhile()` 方法可以从 `Stream` 中依次获取满足条件的元素,直到不满足条件为止结束获取。 + +```java +List integerList = List.of(11, 33, 66, 8, 9, 13); +integerList.stream().takeWhile(x -> x < 50).forEach(System.out::println);// 11 33 +``` + +`dropWhile()` 方法的效果和 `takeWhile()` 相反。 + +```java +List integerList2 = List.of(11, 33, 66, 8, 9, 13); +integerList2.stream().dropWhile(x -> x < 50).forEach(System.out::println);// 66 8 9 13 +``` + +`iterate()` 方法的新重载方法提供了一个 `Predicate` 参数 (判断条件)来决定什么时候结束迭代 + +```java +public static Stream iterate(final T seed, final UnaryOperator f) { +} +// 新增加的重载方法 +public static Stream iterate(T seed, Predicate hasNext, UnaryOperator next) { + +} +``` + +两者的使用对比如下,新的 `iterate()` 重载方法更加灵活一些。 + +```java +// 使用原始 iterate() 方法输出数字 1~10 +Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println); +// 使用新的 iterate() 重载方法输出数字 1~10 +Stream.iterate(1, i -> i <= 10, i -> i + 1).forEach(System.out::println); +``` + +`Optional` 类中新增了 `ifPresentOrElse()`、`or()` 和 `stream()` 等方法 + +`ifPresentOrElse()` 方法接受两个参数 `Consumer` 和 `Runnable` ,如果 `Optional` 不为空调用 `Consumer` 参数,为空则调用 `Runnable` 参数。 + +```java +public void ifPresentOrElse(Consumer action, Runnable emptyAction) + +Optional objectOptional = Optional.empty(); +objectOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Empty!!!"));// Empty!!! +``` + +`or()` 方法接受一个 `Supplier` 参数 ,如果 `Optional` 为空则返回 `Supplier` 参数指定的 `Optional` 值。 + +```java +public Optional or(Supplier> supplier) + +Optional objectOptional = Optional.empty(); +objectOptional.or(() -> Optional.of("java")).ifPresent(System.out::println);//java +``` + +### String 存储结构变更 + +JDK 8 及之前的版本,`String` 一直是用 `char[]` 存储。在 Java 9 之后,`String` 的实现改用 `byte[]` 数组存储字符串。 ### 进程 API -Java 9 增加了 `ProcessHandle` 接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程 +Java 9 增加了 `ProcessHandle` 接口,可以对原生进程进行管理,尤其适合于管理长时间运行的进程。 + +```java +System.out.println(ProcessHandle.current().pid()); +System.out.println(ProcessHandle.current().info()); +``` + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/image-20210816104614414.png) ### 平台日志 API 和服务 @@ -41,21 +170,34 @@ Java 9 允许为 JDK 和应用配置同样的日志实现。新增了 `System.Lo ### 变量句柄 -- 变量句柄是一个变量或一组变量的引用,包括静态域,非静态域,数组元素和堆外数据结构中的组成部分等 -- 变量句柄的含义类似于已有的方法句柄`MethodHandle` -- 由 Java 类`java.lang.invoke.VarHandle` 来表示,可以使用类 `java.lang.invoke.MethodHandles.Lookup` 中的静态工厂方法来创建 `VarHandle` 对 象 +变量句柄是一个变量或一组变量的引用,包括静态域,非静态域,数组元素和堆外数据结构中的组成部分等 + +变量句柄的含义类似于已有的方法句柄 `MethodHandle` ,由 Java 类 `java.lang.invoke.VarHandle` 来表示,可以使用类 `java.lang.invoke.MethodHandles.Lookup` 中的静态工厂方法来创建 `VarHandle` 对象。 + +`VarHandle` 的出现替代了 `java.util.concurrent.atomic` 和 `sun.misc.Unsafe` 的部分操作。并且提供了一系列标准的内存屏障操作,用于更加细粒度的控制内存排序。在安全性、可用性、性能上都要优于现有的 API。 ### 改进方法句柄(Method Handle) -- 方法句柄从 Java7 开始引入,Java9 在类`java.lang.invoke.MethodHandles` 中新增了更多的静态方法来创建不同类型的方法句柄 +方法句柄从 Java7 开始引入,Java9 在类`java.lang.invoke.MethodHandles` 中新增了更多的静态方法来创建不同类型的方法句柄。 + +### 接口私有方法 + +Java 9 允许在接口中使用私有方法。 + +```java +public interface MyInterface { + private void methodPrivate(){ + + } +} +``` ### 其它新特性 -- **接口私有方法** :Java 9 允许在接口中使用私有方法 - **try-with-resources 增强** :在 try-with-resources 语句中可以使用 effectively-final 变量(什么是 effectively-final 变量,见这篇文章 [https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html](https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html)) -- **类 `CompletableFuture` 中增加了几个新的方法(`completeAsync` ,`orTimeout` 等)** -- **Nashorn 引擎的增强** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性 -- **I/O 流的新特性** :增加了新的方法来读取和复制 InputStream 中包含的数据 +- 类 `CompletableFuture` 中增加了几个新的方法(`completeAsync` ,`orTimeout` 等) +- **Nashorn 引擎的增强** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性(Java 11 中已经被弃用)。 +- **I/O 流的新特性** :增加了新的方法来读取和复制 `InputStream` 中包含的数据 - **改进应用的安全性能** :Java 9 新增了 4 个 SHA- 3 哈希算法,SHA3-224、SHA3-256、SHA3-384 和 S HA3-512 - ...... @@ -121,17 +263,17 @@ _Guide 哥:说白点就是多了层封装,JDK 开发组的人没少看市面 //判断字符串是否为空 " ".isBlank();//true //去除字符串首尾空格 -" Java ".strip();// "Java" +" Java ".strip();// "Java" //去除字符串首部空格 -" Java ".stripLeading(); // "Java " +" Java ".stripLeading(); // "Java " //去除字符串尾部空格 -" Java ".stripTrailing(); // " Java" +" Java ".stripTrailing(); // " Java" //重复字符串多少次 -"Java".repeat(3); // "JavaJavaJava" +"Java".repeat(3); // "JavaJavaJava" //返回由行终止符分隔的字符串集合。 -"A\nB\nC".lines().count(); // 3 -"A\nB\nC".lines().collect(Collectors.toList()); +"A\nB\nC".lines().count(); // 3 +"A\nB\nC".lines().collect(Collectors.toList()); ``` ### ZGC:可伸缩低延迟垃圾收集器 @@ -158,31 +300,20 @@ Java 11 对 Java 9 中引入并在 Java 10 中进行了更新的 Http Client API 使用起来也很简单,如下: ```java -var request = HttpRequest.newBuilder() - - .uri(URI.create("https://javastack.cn")) - - .GET() - - .build(); - -var client = HttpClient.newHttpClient(); - -// 同步 - -HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - -System.out.println(response.body()); - -// 异步 - -client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) - - .thenApply(HttpResponse::body) - - .thenAccept(System.out::println); - - +var request = HttpRequest.newBuilder() + .uri(URI.create("https://javastack.cn")) + .GET() + .build(); +var client = HttpClient.newHttpClient(); + +// 同步 +HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); +System.out.println(response.body()); + +// 异步 +client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenApply(HttpResponse::body) + .thenAccept(System.out::println); ``` ### 简化启动单个源代码文件的方法 From 814780f7390af74864cf6b39d78e967157c19bc7 Mon Sep 17 00:00:00 2001 From: guide Date: Mon, 16 Aug 2021 16:42:31 +0800 Subject: [PATCH 12/20] =?UTF-8?q?[feat]java10,11=20=E6=96=B0=E7=89=B9?= =?UTF-8?q?=E6=80=A7=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\346\226\260\347\211\271\346\200\247.md" | 152 +++++++++++++----- 1 file changed, 113 insertions(+), 39 deletions(-) diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" index dc1d4318f74..4354d219507 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" @@ -38,8 +38,8 @@ Java 9 模块的重要特征是在其工件(artifact)的根目录中包含 想要深入了解 Java 9 的模块化,参见: -- [Project Jigsaw: Module System Quick-Start Guide](https://openjdk.java.net/projects/jigsaw/quick-start) -- [Java 9 Modules: part 1](https://stacktraceguru.com/java9/module-introduction) +- [《Project Jigsaw: Module System Quick-Start Guide》](https://openjdk.java.net/projects/jigsaw/quick-start) +- [《Java 9 Modules: part 1》](https://stacktraceguru.com/java9/module-introduction) ### Jshell @@ -59,6 +59,8 @@ Set.of("Java", "C++"); Map.of("Java", 1, "C++", 2)`; ``` +使用 `of()` 创建的集合为不可变集合,不能进行添加、删除、替换、 排序等操作,不然会报 `java.lang.UnsupportedOperationException` 异常。 + `Collectors` 中增加了新的方法 `filtering()` 和 `flatMapping()`。 `Collectors` 的 `filtering()` 方法类似于 `Stream` 类的 `filter()` 方法,都是用于过滤元素。 @@ -165,8 +167,9 @@ Java 9 允许为 JDK 和应用配置同样的日志实现。新增了 `System.Lo ### 反应式流 ( Reactive Streams ) -- 在 Java9 中的 `java.util.concurrent.Flow` 类中新增了反应式流规范的核心接口 -- Flow 中包含了 `Flow.Publisher`、`Flow.Subscriber`、`Flow.Subscription` 和 `Flow.Processor` 等 4 个核心接口。Java 9 还提供了`SubmissionPublisher` 作为`Flow.Publisher` 的一个实现。 +在 Java9 中的 `java.util.concurrent.Flow` 类中新增了反应式流规范的核心接口 。 + +`Flow` 中包含了 `Flow.Publisher`、`Flow.Subscriber`、`Flow.Subscription` 和 `Flow.Processor` 等 4 个核心接口。Java 9 还提供了`SubmissionPublisher` 作为`Flow.Publisher` 的一个实现。 ### 变量句柄 @@ -192,9 +195,9 @@ public interface MyInterface { } ``` -### 其它新特性 +### Java9 其它新特性 -- **try-with-resources 增强** :在 try-with-resources 语句中可以使用 effectively-final 变量(什么是 effectively-final 变量,见这篇文章 [https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html](https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html)) +- **try-with-resources 增强** :在 try-with-resources 语句中可以使用 effectively-final 变量(什么是 effectively-final 变量,见这篇文章:[《Effectively Final Variables in Java》](https://ilkinulas.github.io/programming/java/2016/03/27/effectively-final-java.html) - 类 `CompletableFuture` 中增加了几个新的方法(`completeAsync` ,`orTimeout` 等) - **Nashorn 引擎的增强** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性(Java 11 中已经被弃用)。 - **I/O 流的新特性** :增加了新的方法来读取和复制 `InputStream` 中包含的数据 @@ -205,16 +208,45 @@ public interface MyInterface { 发布于 2018 年 3 月 20 日,最知名的特性应该是 var 关键字(局部变量类型推断)的引入了,其他还有垃圾收集器改善、GC 改进、性能提升、线程管控等一批新特性 -### var 关键字 +### var(局部变量推断) + +由于太多 Java 开发者希望 Java 中引入局部变量推断,于是 Java 10 的时候它来了,也算是众望所归了! + +Java 10 提供了 var 关键字声明局部变量。 + +> Scala 和 Kotlin 中有 val 关键字 ( `final var` 组合关键字),Java10 中并没有引入。 + +Java 10 只引入了 var,而 + +```java +var id = 0; +var codefx = new URL("https://mp.weixin.qq.com/"); +var list = new ArrayList<>(); +var list = List.of(1, 2, 3); +var map = new HashMap(); +var p = Paths.of("src/test/java/Java9FeaturesTest.java"); +var numbers = List.of("a", "b", "c"); +for (var n : list) + System.out.print(n+ " "); +``` + +var 关键字只能用于带有构造器的局部变量和 for 循环中。 + +```java +var count=null; //❌编译不通过,不能声明为 null +var r = () -> Math.random();//❌编译不通过,不能声明为 Lambda表达式 +var array = {1,2,3};//❌编译不通过,不能声明数组 +``` + +var 并不会改变 Java 是一门静态类型语言的事实,编译器负责推断出类型。 -- **介绍** :提供了 var 关键字声明局部变量:`var list = new ArrayList(); // ArrayList` -- **局限性** :只能用于带有构造器的**局部变量**和 for 循环中 +相关阅读:[《Java 10 新特性之局部变量类型推断》](https://zhuanlan.zhihu.com/p/34911982)。 -_Guide 哥:实际上 Lombok 早就体用了一个类似的关键字,使用它可以简化代码,但是可能会降低程序的易读性、可维护性。一般情况下,我个人都不太推荐使用。_ +### 集合增强 -### 不可变集合 +`list`,`set`,`map` 提供了静态方法`copyOf()`返回入参集合的一个不可变拷贝。 -**list,set,map 提供了静态方法`copyOf()`返回入参集合的一个不可变拷贝(以下为 JDK 的源码)** +以下为 JDK 的源码: ```java static List copyOf(Collection coll) { @@ -222,11 +254,26 @@ static List copyOf(Collection coll) { } ``` -**`java.util.stream.Collectors`中新增了静态方法,用于将流中的元素收集为不可变的集合** +使用 `copyOf()` 创建的集合为不可变集合,不能进行添加、删除、替换、 排序等操作,不然会报 `java.lang.UnsupportedOperationException` 异常。 IDEA 也会有相应的提示。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/image-20210816154125579.png) + +`java.util.stream.Collectors` 中新增了静态方法,用于将流中的元素收集为不可变的集合。 + +```java +var list = new ArrayList<>(); +list.stream().collect(Collectors.toUnmodifiableList()); +list.stream().collect(Collectors.toUnmodifiableSet()); +``` ### Optional -- 新增了`orElseThrow()`方法来在没有值时抛出异常 +新增了`orElseThrow()`方法来在没有值时抛出指定的异常。 + +```java +Optional.ofNullable(cache.getIfPresent(key)) + .orElseThrow(() -> new PrestoException(NOT_FOUND, "Missing entry found for key: " + key)); +``` ### 并行全垃圾回收器 G1 @@ -240,12 +287,12 @@ static List copyOf(Collection coll) { Java 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。CDS 特性在原来的 bootstrap 类基础之上,扩展加入了应用类的 CDS (Application Class-Data Sharing) 支持。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升 -### 其他特性 +### Java10 其他新特性 - **线程-局部管控**:Java 10 中线程管控引入 JVM 安全点的概念,将允许在不运行全局 JVM 安全点的情况下实现线程回调,由线程本身或者 JVM 线程来执行,同时保持线程处于阻塞状态,这种方式使得停止单个线程变成可能,而不是只能启用或停止所有线程 - - **备用存储装置上的堆分配**:Java 10 中将使得 JVM 能够使用适用于不同类型的存储机制的堆,在可选内存设备上进行堆内存分配 - **统一的垃圾回收接口**:Java 10 中,hotspot/gc 代码实现方面,引入一个干净的 GC 接口,改进不同 GC 源代码的隔离性,多个 GC 之间共享的实现细节代码应该存在于辅助类中。统一垃圾回收接口的主要原因是:让垃圾回收器(GC)这部分代码更加整洁,便于新人上手开发,便于后续排查相关问题。 +- ...... ## Java11 @@ -253,11 +300,11 @@ Java11 于 2018 年 9 月 25 日正式发布,这是很重要的一个版本! ![](https://img-blog.csdnimg.cn/20210603202746605.png) -### 字符串加强 +### String Java 11 增加了一系列的字符串处理方法,如以下所示。 -_Guide 哥:说白点就是多了层封装,JDK 开发组的人没少看市面上常见的工具类框架啊!_ +_Guide:说白点就是多了层封装,JDK 开发组的人没少看市面上常见的工具类框架啊!_ ```java //判断字符串是否为空 @@ -276,6 +323,15 @@ _Guide 哥:说白点就是多了层封装,JDK 开发组的人没少看市面 "A\nB\nC".lines().collect(Collectors.toList()); ``` +### Optional + +新增了`empty()`方法来判断指定的 `Optional` 对象是否为空。 + +```java +var op = Optional.empty(); +System.out.println(op.isEmpty());//判断指定的 Optional 对象是否为空 +``` + ### ZGC:可伸缩低延迟垃圾收集器 **ZGC 即 Z Garbage Collector**,是一个可伸缩的、低延迟的垃圾收集器。 @@ -289,15 +345,19 @@ ZGC 主要为了满足如下目标进行设计: - 针以及 Load barriers 优化奠定基础 - 当前只支持 Linux/x64 位平台 -ZGC 目前 **处在实验阶段**,只支持 Linux/x64 平台 +ZGC 目前 **处在实验阶段**,只支持 Linux/x64 平台。 + +与 CMS 中的 ParNew 和 G1 类似,ZGC 也采用标记-复制算法,不过 ZGC 对该算法做了重大改进。 + +在 ZGC 中出现 Stop The World 的情况会更少! + +详情可以看 : [《新一代垃圾回收器 ZGC 的探索与实践》](https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html) ### 标准 HTTP Client 升级 Java 11 对 Java 9 中引入并在 Java 10 中进行了更新的 Http Client API 进行了标准化,在前两个版本中进行孵化的同时,Http Client 几乎被完全重写,并且现在完全支持异步非阻塞。 -并且,Java11 中,Http Client 的包名由 `jdk.incubator.http` 改为`java.net.http`,该 API 通过 `CompleteableFuture` 提供非阻塞请求和响应语义。 - -使用起来也很简单,如下: +并且,Java11 中,Http Client 的包名由 `jdk.incubator.http` 改为`java.net.http`,该 API 通过 `CompleteableFuture` 提供非阻塞请求和响应语义。使用起来也很简单,如下: ```java var request = HttpRequest.newBuilder() @@ -316,28 +376,42 @@ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenAccept(System.out::println); ``` -### 简化启动单个源代码文件的方法 +### var(Lambda 参数的局部变量语法) -- 增强了 Java 启动器,使其能够运行单一文件的 Java 源代码。此功能允许使用 Java 解释器直接执行 Java 源代码。源代码在内存中编译,然后由解释器执行。唯一的约束在于所有相关的类必须定义在同一个 Java 文件中 -- 对于 Java 初学者并希望尝试简单程序的人特别有用,并且能和 jshell 一起使用 -- 一定能程度上增强了使用 Java 来写脚本程序的能力 +从 Java 10 开始,便引入了局部变量类型推断这一关键特性。类型推断允许使用关键字 var 作为局部变量的类型而不是实际类型,编译器根据分配给变量的值推断出类型。 -### 用于 Lambda 参数的局部变量语法 +Java 10 中对 var 关键字存在几个限制 -- 从 Java 10 开始,便引入了局部变量类型推断这一关键特性。类型推断允许使用关键字 var 作为局部变量的类型而不是实际类型,编译器根据分配给变量的值推断出类型 -- Java 10 中对 var 关键字存在几个限制 - - 只能用于局部变量上 - - 声明时必须初始化 - - 不能用作方法参数 - - 不能在 Lambda 表达式中使用 -- Java11 开始允许开发者在 Lambda 表达式中使用 var 进行参数声明 +- 只能用于局部变量上 +- 声明时必须初始化 +- 不能用作方法参数 +- 不能在 Lambda 表达式中使用 -### 其他特性 +Java11 开始允许开发者在 Lambda 表达式中使用 var 进行参数声明。 + +```java +// 下面两者是等价的 +Consumer consumer = (var i) -> System.out.println(i); +Consumer consumer = (String i) -> System.out.println(i); +``` + +### 启动单文件源代码程序 + +[JEP 330:启动单文件源代码程序(aunch Single-File Source-Code Programs)](https://openjdk.java.net/jeps/330) 可以让我们运行单一文件的 Java 源代码。此功能允许使用 Java 解释器直接执行 Java 源代码。源代码在内存中编译,然后由解释器执行,不需要在磁盘上生成 `.class` 文件了。 -- 新的垃圾回收器 Epsilon,一个完全消极的 GC 实现,分配有限的内存资源,最大限度的降低内存占用和内存吞吐延迟时间 -- 低开销的 Heap Profiling:Java 11 中提供一种低开销的 Java 堆分配采样方法,能够得到堆分配的 Java 对象信息,并且能够通过 JVMTI 访问堆信息 -- TLS1.3 协议:Java 11 中包含了传输层安全性(TLS)1.3 规范(RFC 8446)的实现,替换了之前版本中包含的 TLS,包括 TLS 1.2,同时还改进了其他 TLS 功能,例如 OCSP 装订扩展(RFC 6066,RFC 6961),以及会话散列和扩展主密钥扩展(RFC 7627),在安全性和性能方面也做了很多提升 -- 飞行记录器:飞行记录器之前是商业版 JDK 的一项分析工具,但在 Java 11 中,其代码被包含到公开代码库中,这样所有人都能使用该功能了 +唯一的约束在于所有相关的类必须定义在同一个 Java 文件中。 + +对于 Java 初学者并希望尝试简单程序的人特别有用,并且能和 jshell 一起使用 + +一定能程度上增强了使用 Java 来写脚本程序的能力。 + +### Java11 其他新特性 + +- **新的垃圾回收器 Epsilon** :一个完全消极的 GC 实现,分配有限的内存资源,最大限度的降低内存占用和内存吞吐延迟时间 +- **低开销的 Heap Profiling** :Java 11 中提供一种低开销的 Java 堆分配采样方法,能够得到堆分配的 Java 对象信息,并且能够通过 JVMTI 访问堆信息 +- **TLS1.3 协议** :Java 11 中包含了传输层安全性(TLS)1.3 规范(RFC 8446)的实现,替换了之前版本中包含的 TLS,包括 TLS 1.2,同时还改进了其他 TLS 功能,例如 OCSP 装订扩展(RFC 6066,RFC 6961),以及会话散列和扩展主密钥扩展(RFC 7627),在安全性和性能方面也做了很多提升 +- **飞行记录器(Java Flight Recorder)** :飞行记录器之前是商业版 JDK 的一项分析工具,但在 Java 11 中,其代码被包含到公开代码库中,这样所有人都能使用该功能了。 +- ...... ## Java12 From e4bb8f845fa8a3e269597f26db3166a975822230 Mon Sep 17 00:00:00 2001 From: guide Date: Tue, 17 Aug 2021 14:39:54 +0800 Subject: [PATCH 13/20] =?UTF-8?q?[fix]=E5=AD=97=E7=AC=A6=E4=B8=B2=E6=8B=BC?= =?UTF-8?q?=E6=8E=A5=E5=9B=BE=E7=89=87=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...205\345\255\230\345\214\272\345\237\237.md" | 2 +- ...345\270\270\351\207\217\346\261\240.drawio" | 1 + ...5-\345\270\270\351\207\217\346\261\240.png" | Bin 0 -> 150195 bytes ...-\345\270\270\351\207\217\346\261\2402.png" | Bin 34188 -> 0 bytes 4 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 "docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio" create mode 100644 "docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png" delete mode 100644 "docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png" diff --git "a/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md" "b/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md" index 11210af18d8..918585a0d6e 100644 --- "a/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md" +++ "b/docs/java/jvm/Java\345\206\205\345\255\230\345\214\272\345\237\237.md" @@ -371,7 +371,7 @@ System.out.println(str3 == str5);//true System.out.println(str4 == str5);//false ``` -![字符串拼接](./pictures/java内存区域/字符串拼接-常量池2.png) +![字符串拼接](./pictures/java内存区域/字符串拼接-常量池.png) 尽量避免多个字符串拼接,因为这样会重新创建对象。如果需要改变字符串的话,可以使用 StringBuilder 或者 StringBuffer。 diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio" new file mode 100644 index 00000000000..764cc0be828 --- /dev/null +++ "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.drawio" @@ -0,0 +1 @@ +7Vpdb6M4FP011j61AoMNPCZpZkYrrbRStZqZRxccsOLgDDhNMr9+bTAhfKSTtqG0melL8L3mYp9zbny5DXBmq93njKyTf0REOYBWtAPOHYDQti2sPrRlX1r8AJaGOGORmVQb7tlPaoyWsW5YRPPGRCkEl2zdNIYiTWkoGzaSZWLbnLYQvPnUNYlpx3AfEt61fmWRTMwuoFfbv1AWJ9WTbRyUnhWpJpud5AmJxPbI5MyBM8uEkOXVajejXINX4VLe9+mE97CwjKbynBuW6c/Zcu/fPOZp8vjfarvJ/57cmCiPhG/MhgHEXMWbLoQKq1Yt9wYK/GMjKsdNXhA1UROgs97VTnUV689cZnYVSS2pDFa6DBqHuDATmzSiepW2cm8TJun9moTau1WiUrZErrhxx5zkubk+IFoMllSGiRmYXdFM0t1JuOwDCUq9VKyozPZqirnBN7QZ3TqeGW9rFdiWsSVHCkDGRozw4kPkmht1Yeh5BlVwOKrQVVGF0dhUOcNR5V4VVcgfmyp3OKqc66LKHpsqNBxV8Kqoct2xqcI9VH0IJCFCTSitLpSOi7pQOtZQWHonZZ+vSfpy2dcWlQANd5UJZfwPlQmHMq3izxk7FfzB6WNpfLX0jV4fBAMdOo3sO8XgBzyK2gyi0ROwqlueOoxUGLbO6a9xFMrDpN6bOmMV1YzzmeAiK8I4EaH+Iiw5FUt65MGhTx8Wg59ePr6FrQOsp2yD2LvtOcKgjYaioKfNMEdgYgEfd7hQ25dN0JtopiKlLeiNiXAWp2oYKriosk81mCwkfGIcKxZF/BTLdT5ZPUSrTDTNKTu4DFlu0HptrcqKI6bcnkSBgyVKT4dBs3QHAg/MPTCZgQkGcxdMfTAtXPrCB/MA+B7wP4E5BlNbs/q7UuqgTv6hoMuqDfvzbzBi+/oR7W/ANJrodqnGWp8VLGwS1kaL7pj8Znz6+rsGWe2qHN3tDObFYG8G5UNp1Om4tvBVCxObLKRPbamcJ0kWU/mr4rnL1xEZ6ImzKKOcSPbYXG4fPeYJ/wpW1ASVfk69l1Uhym2au2qSO4Gg0wzkBK1AJQ6dQIVaDtt+hYD6uiSDCMh7MwWhMxXkj6qgdjVlv1RBsCVF/MYK6mvevFJBFxSDe6YYgnclBv9CYjjU6G8lhm576K8zaoaMqpcq8lBM0F8Ga72+YsVoCtDds6oFTh4on5JwGRc1wlGlvij+nlMfmH89mpWBA7rHQnwiKU5WE9ati3CDqOrYe6mQqiliscjpMNSe7lb9eV/uLRmx26AYj967tfs6Vh+7WnTO/Hq331W5iC9VLqK3Lhf7mmavVVCq1vSt0okeHGlID2sRFaPnq+idH/5tcXjoMuLAGF1IHGpY/5qlnF7/JsiZ/w8= \ No newline at end of file diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\240.png" new file mode 100644 index 0000000000000000000000000000000000000000..4c6f20e9508bef66557d4663479dea4781de97a7 GIT binary patch literal 150195 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

siZ`Z7(bG>kkS_+iw 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éM-Aa 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 literal 0 HcmV?d00001 diff --git "a/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png" "b/docs/java/jvm/pictures/java\345\206\205\345\255\230\345\214\272\345\237\237/\345\255\227\347\254\246\344\270\262\346\213\274\346\216\245-\345\270\270\351\207\217\346\261\2402.png" deleted file mode 100644 index b680fb60204100c6386c245a3eabc918215c9e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34188 zcmc$_^FYwti0>2Q;NXyHs6z~KaBiIee_Dk2 zK#M|zZWay>fxWM)sjqv0qqCa>4kt+Ezh9i9!cIsZUrrE&Q&bd%LJ8V?+n@xUk-&ez zC3mE~v!kH-gi3FMSGcd*rR_PrSeBq<1z0GfHU)QxqtIYm`~-)_#X4!{@G!Oj(V(?!L}8|eFkU4boj5;-ofA54tVBGt0$lUpa0!_(*jZj6m9QpgYdR- z2QEARPmvyWZen^;#%Om{C$NSi!c-Wojs9-{4;w)Ie`}!+3?(4)-yq^JZ*4nYAB38| zu#GXyQ5UWPc6Bgx1?J=GVQc7aC+_NMYN)BHf-yAHQ`h1Y1?$57wNVIH_>KBiU7P{^ zt9g2Q=)iSR+At7APuWP)Ow9?StBaJ<^l%0AujZhtVg@$#1_vNDT~tsITWL3pIMOJ< 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 Date: Tue, 17 Aug 2021 18:17:10 +0800 Subject: [PATCH 14/20] =?UTF-8?q?Update=20=E4=B8=80=E6=96=87=E5=B8=A6?= =?UTF-8?q?=E4=BD=A0=E7=9C=8B=E9=81=8DJDK9=E5=88=B014=E7=9A=84=E9=87=8D?= =?UTF-8?q?=E8=A6=81=E6=96=B0=E7=89=B9=E6=80=A7.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\346\226\260\347\211\271\346\200\247.md" | 148 ++++++++++++++---- 1 file changed, 115 insertions(+), 33 deletions(-) diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" index 4354d219507..552b03f0967 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" @@ -415,43 +415,133 @@ Consumer consumer = (String i) -> System.out.println(i); ## Java12 -### 增强 Switch +### String -- 传统的 switch 语法存在容易漏写 break 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复 +Java 11 增加了两个的字符串处理方法,如以下所示。 -- Java12 提供了 swtich 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break +`indent()` 方法可以实现字符串缩进。 -- 作为预览特性加入,需要在`javac`编译和`java`运行时增加参数`--enable-preview` +```java +String text = "Java"; +// 缩进 4 格 +text = text.indent(4); +System.out.println(text); +text = text.indent(-10); +System.out.println(text); +``` - ```java - switch (day) { - case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); - case TUESDAY -> System.out.println(7); - case THURSDAY, SATURDAY -> System.out.println(8); - case WEDNESDAY -> System.out.println(9); - } - ``` +输出: + +``` + Java +Java +``` + +`transform()` 方法可以用来转变指定字符串。 + +```java +String result = "foo".transform(input -> input + " bar"); +System.out.println(result); // foo bar +``` + +### 文件比较 + +Java 12 添加了以下方法来比较两个文件: + +```java +public static long mismatch(Path path, Path path2) throws IOException +``` + +`mismatch()` 方法用于比较两个文件,并返回第一个不匹配字符的位置,如果文件相同则返回 -1L。 + +代码示例(两个文件内容相同的情况): + +```java +Path filePath1 = Files.createTempFile("file1", ".txt"); +Path filePath2 = Files.createTempFile("file2", ".txt"); +Files.writeString(filePath1, "Java 12 Article"); +Files.writeString(filePath2, "Java 12 Article"); + +long mismatch = Files.mismatch(filePath1, filePath2); +assertEquals(-1, mismatch); +``` + +代码示例(两个文件内容不相同的情况): + +```java +Path filePath3 = Files.createTempFile("file3", ".txt"); +Path filePath4 = Files.createTempFile("file4", ".txt"); +Files.writeString(filePath3, "Java 12 Article"); +Files.writeString(filePath4, "Java 12 Tutorial"); + +long mismatch = Files.mismatch(filePath3, filePath4); +assertEquals(8, mismatch); +``` ### 数字格式化工具类 -- `NumberFormat` 新增了对复杂的数字进行格式化的支持 +`NumberFormat` 新增了对复杂的数字进行格式化的支持 - ```java - NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); - String result = fmt.format(1000); - System.out.println(result); // 输出为 1K,计算工资是多少K更方便了。。。 - ``` +```java +NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); +String result = fmt.format(1000); + System.out.println(result); // 输出为 1K,计算工资是多少K更方便了。。。 +``` ### Shenandoah GC -- Redhat 主导开发的 Pauseless GC 实现,主要目标是 99.9% 的暂停小于 10ms,暂停与堆大小无关等 -- 和 Java11 开源的 ZGC 相比(需要升级到 JDK11 才能使用),Shenandoah GC 有稳定的 JDK8u 版本,在 Java8 占据主要市场份额的今天有更大的可落地性 +Redhat 主导开发的 Pauseless GC 实现,主要目标是 99.9% 的暂停小于 10ms,暂停与堆大小无关等 + +和 Java11 开源的 ZGC 相比(需要升级到 JDK11 才能使用),Shenandoah GC 有稳定的 JDK8u 版本,在 Java8 占据主要市场份额的今天有更大的可落地性。 ### G1 收集器提升 -- **Java12 为默认的垃圾收集器 G1 带来了两项更新:** - - 可中止的混合收集集合:JEP344 的实现,为了达到用户提供的停顿时间目标,JEP 344 通过把要被回收的区域集(混合收集集合)拆分为强制和可选部分,使 G1 垃圾回收器能中止垃圾回收过程。 G1 可以中止可选部分的回收以达到停顿时间目标 - - 及时返回未使用的已分配内存:JEP346 的实现,增强 G1 GC,以便在空闲时自动将 Java 堆内存返回给操作系统 +Java12 为默认的垃圾收集器 G1 带来了两项更新: + +- **可中止的混合收集集合** :JEP344 的实现,为了达到用户提供的停顿时间目标,JEP 344 通过把要被回收的区域集(混合收集集合)拆分为强制和可选部分,使 G1 垃圾回收器能中止垃圾回收过程。 G1 可以中止可选部分的回收以达到停顿时间目标 +- **及时返回未使用的已分配内存** :JEP346 的实现,增强 G1 GC,以便在空闲时自动将 Java 堆内存返回给操作系统 + +### 预览新特性 + +作为预览特性加入,需要在`javac`编译和`java`运行时增加参数`--enable-preview` 。 + +#### 增强 Switch + +传统的 `switch` 语法存在容易漏写 `break` 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复 + +Java12 提供了 `swtich` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。 + +```java +switch (day) { + case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); + case TUESDAY -> System.out.println(7); + case THURSDAY, SATURDAY -> System.out.println(8); + case WEDNESDAY -> System.out.println(9); +} +``` + +#### instanceof 模式匹配 + +`instanceof` 主要在**类型强转前探测对象的具体类型**。 + +之前的版本中,我们需要显示地对对象进行类型转换。 + +```java +Object obj = "我是字符串"; +if(obj instanceof String){ + String str = (String) obj; + System.out.println(str); +} +``` + +新版的 `instanceof` 可以在判断是否属于具体的类型同时完成转换。 + +```java +Object obj = "我是字符串"; +if(obj instanceof String str){ + System.out.println(str); +} +``` ## Java13 @@ -599,16 +689,7 @@ switch (day) { ### instanceof 增强 -- instanceof 主要在**类型强转前探测对象的具体类型**,然后执行具体的强转 - -- 新版的 instanceof 可以在判断的是否属于具体的类型同时完成转换 - -```java -Object obj = "我是字符串"; -if(obj instanceof String str){ - System.out.println(str); -} -``` +依然是**预览特性** ,Java 12 新特性中介绍过。 ### 其他特性 @@ -640,6 +721,7 @@ if(obj instanceof String str){ - Java 11 – Features and Comparison: - Oracle Java12 ReleaseNote - Oracle Java13 ReleaseNote +- New Features in Java 12 - New Java13 Features - Java13 新特性概述 - Oracle Java14 record From e7e8d481d2c5a8a888de7cfaada10affb31356ed Mon Sep 17 00:00:00 2001 From: guide Date: Wed, 18 Aug 2021 08:47:59 +0800 Subject: [PATCH 15/20] =?UTF-8?q?[feat]=20Java13=E6=96=B0=E7=89=B9?= =?UTF-8?q?=E6=80=A7=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\346\226\260\347\211\271\346\200\247.md" | 131 ++++++++++++++---- 1 file changed, 103 insertions(+), 28 deletions(-) diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" index 552b03f0967..1e7ba1759d2 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" @@ -1,5 +1,9 @@ Java 8 新特性见这里:[Java8 新特性最佳指南](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247484744&idx=1&sn=9db31dca13d327678845054af75efb74&chksm=cea24a83f9d5c3956f4feb9956b068624ab2fdd6c4a75fe52d5df5dca356a016577301399548&token=1082669959&lang=zh_CN&scene=21#wechat_redirect) 。 +你可以在 [Archived OpenJDK General-Availability Releases](http://jdk.java.net/archive/) 上下载自己需要的 JDK 版本! + +官方的新特性说明文档地址: https://openjdk.java.net/projects/jdk/ 。 + _Guide 哥:别人家的特性都用了几年了,我 Java 才出来,哈哈!真实!_ ## Java9 @@ -281,11 +285,11 @@ Optional.ofNullable(cache.getIfPresent(key)) 为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始,G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。 -### 应用程序类数据共享 +### 应用程序类数据共享(扩展CDS功能) -在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing,简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机(JVM)共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用 +在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing,简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机(JVM)共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。 -Java 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。CDS 特性在原来的 bootstrap 类基础之上,扩展加入了应用类的 CDS (Application Class-Data Sharing) 支持。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升 +Java 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。CDS 特性在原来的 bootstrap 类基础之上,扩展加入了应用类的 CDS 为 (Application Class-Data Sharing,AppCDS) 支持,大大加大了 CDS 的适用范围。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升。 ### Java10 其他新特性 @@ -545,35 +549,25 @@ if(obj instanceof String str){ ## Java13 -### 引入 yield 关键字到 Switch 中 - -- `Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值 +### 预览新特性 -- `yield`和 `return` 的区别在于:`return` 会直接跳出当前循环或者方法,而 `yield` 只会跳出当前 `Switch` 块,同时在使用 `yield` 时,需要有 `default` 条件 +#### 文本块 - ```java - private static String descLanguage(String name) { - return switch (name) { - case "Java": yield "object-oriented, platform independent and secured"; - case "Ruby": yield "a programmer's best friend"; - default: yield name +" is a good language"; - }; - } - ``` +解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本 -### 文本块 +两个`"""`中间的任何内容都会被解释为字符串的一部分,包括换行符。 -- 解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本 - -- 两个`"""`中间的任何内容都会被解释为字符串的一部分,包括换行符 +未支持文本块之前的 HTML 写法: ```java String json ="{\n" + " \"name\":\"mkyong\",\n" + " \"age\":38\n" + - "}\n"; // 未支持文本块之前 + "}\n"; ``` +支持文本块之后的 HTML 写法: + ```java String json = """ @@ -584,19 +578,100 @@ if(obj instanceof String str){ """; ``` -### 增强 ZGC 释放未使用内存 +未支持文本块之前的 SQL 写法: + +```sql +String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" + + "WHERE `CITY` = 'INDIANAPOLIS'\n" + + "ORDER BY `EMP_ID`, `LAST_NAME`;\n"; +``` + +支持文本块之后的 SQL 写法: + +```sql +String query = """ + SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` + WHERE `CITY` = 'INDIANAPOLIS' + ORDER BY `EMP_ID`, `LAST_NAME`; + """; +``` + +另外,`String` 类新增加了 3 个新的方法来操作文本块: + +- `formatted(Object... args)` :它类似于 `String` 的` format() `方法。添加它是为了支持文本块的格式设置。 +- `stripIndent()` :用于去除文本块中每一行开头和结尾的空格。 +- `translateEscapes()` :转义序列如 *“\\\t”* 转换为 *“\t”* + +由于文本块是一项预览功能,可以在未来版本中删除,因此这些新方法被标记为弃用。 + +```java +@Deprecated(forRemoval=true, since="13") +public String stripIndent() { +} +@Deprecated(forRemoval=true, since="13") +public String formatted(Object... args) { + +} +@Deprecated(forRemoval=true, since="13") +public String translateEscapes() { +} +``` -- 在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题 -- ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织 -- 在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用 +#### Switch(引入 yield 关键字到 Switch 中) + +`Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值 + +`yield`和 `return` 的区别在于:`return` 会直接跳出当前循环或者方法,而 `yield` 只会跳出当前 `Switch` 块,同时在使用 `yield` 时,需要有 `default` 条件 + +```java + private static String descLanguage(String name) { + return switch (name) { + case "Java": yield "object-oriented, platform independent and secured"; + case "Ruby": yield "a programmer's best friend"; + default: yield name +" is a good language"; + }; + } +``` + +### 增强 ZGC(释放未使用内存) + +在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。 + +ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织。 + +在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。 ### SocketAPI 重构 -- Java 13 为 Socket API 带来了新的底层实现方法,并且在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 +Java Socket API 终于迎来了重大更新! -### 动态应用程序类-数据共享 +Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 ``PlainSocketImpl`` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 -- Java 13 中对 Java 10 中引入的 应用程序类数据共享进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括:所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类 +并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 + +```java +public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { +} +``` + +### FileSystems + +`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序: + +- `newFileSystem(Path)` +- `newFileSystem(Path, Map)` +- `newFileSystem(Path, Map, ClassLoader)` + +### 动态 CDS 存档 + +Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。 + +这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。 + +```bash +$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar +$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar +``` ## Java14 From 801c2200fc2262f8515e752d114228a8905d99bd Mon Sep 17 00:00:00 2001 From: guide Date: Wed, 18 Aug 2021 09:36:54 +0800 Subject: [PATCH 16/20] =?UTF-8?q?[feat]=20Java14=E6=96=B0=E7=89=B9?= =?UTF-8?q?=E6=80=A7=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...01\346\226\260\347\211\271\346\200\247.md" | 238 ++++++++++-------- 1 file changed, 131 insertions(+), 107 deletions(-) diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" index 1e7ba1759d2..cb0669f3b32 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" @@ -285,7 +285,7 @@ Optional.ofNullable(cache.getIfPresent(key)) 为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始,G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。 -### 应用程序类数据共享(扩展CDS功能) +### 应用程序类数据共享(扩展 CDS 功能) 在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing,简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机(JVM)共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。 @@ -513,7 +513,7 @@ Java12 为默认的垃圾收集器 G1 带来了两项更新: 传统的 `switch` 语法存在容易漏写 `break` 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复 -Java12 提供了 `swtich` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。 +Java12 增强了 `swtich` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。 ```java switch (day) { @@ -553,30 +553,30 @@ if(obj instanceof String str){ #### 文本块 -解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本 +解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本。 -两个`"""`中间的任何内容都会被解释为字符串的一部分,包括换行符。 +Java 13 支持两个 `"""` 符号中间的任何内容都会被解释为字符串的一部分,包括换行符。 未支持文本块之前的 HTML 写法: - ```java - String json ="{\n" + - " \"name\":\"mkyong\",\n" + - " \"age\":38\n" + - "}\n"; - ``` +```java +String json ="{\n" + + " \"name\":\"mkyong\",\n" + + " \"age\":38\n" + + "}\n"; +``` 支持文本块之后的 HTML 写法: - ```java - - String json = """ - { - "name":"mkyong", - "age":38 - } - """; - ``` +```java + + String json = """ + { + "name":"mkyong", + "age":38 + } + """; +``` 未支持文本块之前的 SQL 写法: @@ -598,9 +598,9 @@ String query = """ 另外,`String` 类新增加了 3 个新的方法来操作文本块: -- `formatted(Object... args)` :它类似于 `String` 的` format() `方法。添加它是为了支持文本块的格式设置。 +- `formatted(Object... args)` :它类似于 `String` 的`format()`方法。添加它是为了支持文本块的格式设置。 - `stripIndent()` :用于去除文本块中每一行开头和结尾的空格。 -- `translateEscapes()` :转义序列如 *“\\\t”* 转换为 *“\t”* +- `translateEscapes()` :转义序列如 _“\\\t”_ 转换为 _“\t”_ 由于文本块是一项预览功能,可以在未来版本中删除,因此这些新方法被标记为弃用。 @@ -610,14 +610,14 @@ public String stripIndent() { } @Deprecated(forRemoval=true, since="13") public String formatted(Object... args) { - + } @Deprecated(forRemoval=true, since="13") public String translateEscapes() { } ``` -#### Switch(引入 yield 关键字到 Switch 中) +#### 增强 Switch(引入 yield 关键字到 Switch 中) `Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值 @@ -645,7 +645,7 @@ ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages Java Socket API 终于迎来了重大更新! -Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 ``PlainSocketImpl`` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 +Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 @@ -675,120 +675,143 @@ $ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar ## Java14 -### record 关键字 - -- 简化数据类的定义方式,使用 record 代替 class 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 toString,hashCode,equals 方法 - -- 类似于使用 Class 定义类,同时使用了 lomobok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解 - -- 作为预览特性引入 - - ```java - /** - * 这个类具有两个特征 - * 1. 所有成员属性都是final - * 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个) - * 那么这种类就很适合使用record来声明 - */ - final class Rectangle implements Shape { - final double length; - final double width; - - public Rectangle(double length, double width) { - this.length = length; - this.width = width; - } - - double length() { return length; } - double width() { return width; } - } - /** - * 1. 使用record声明的类会自动拥有上面类中的三个方法 - * 2. 在这基础上还附赠了equals(),hashCode()方法以及toString()方法 - * 3. toString方法中包括所有成员属性的字符串表示形式及其名称 - */ - record Rectangle(float length, float width) { } - ``` - ### 空指针异常精准提示 -- 通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题 +通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题。 - ```java - a.b.c.i = 99; // 假设这段代码会发生空指针 - ``` +```java +a.b.c.i = 99; // 假设这段代码会发生空指针 +``` - ```java - Exception in thread "main" java.lang.NullPointerException: - Cannot read field 'c' because 'a.b' is null. - at Prog.main(Prog.java:5) // 增加参数后提示的异常中很明确的告知了哪里为空导致 - ``` +Java 14 之前: -### switch 的增强终于转正 +```java +Exception in thread "main" java.lang.NullPointerException + at NullPointerExample.main(NullPointerExample.java:5) +``` -- JDK12 引入的 switch(预览特性)在 JDK14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用 -- 主要是用`->`来替代以前的`:`+`break`;另外就是提供了 yield 来在 block 中返回值 +Java 14 之后: -_Before Java 14_ +```java + // 增加参数后提示的异常中很明确的告知了哪里为空导致 +Exception in thread "main" java.lang.NullPointerException: + Cannot read field 'c' because 'a.b' is null. + at Prog.main(Prog.java:5) +``` + +### switch 的增强(转正) + +Java12 引入的 switch(预览特性)在 Java14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用。 + +Java12 为 switch 表达式引入了类似 lambda 语法条件匹配成功后的执行块,不需要多写 break ,Java13 提供了 `yield` 来在 block 中返回值。 ```java -switch (day) { - case MONDAY: - case FRIDAY: - case SUNDAY: - System.out.println(6); - break; - case TUESDAY: - System.out.println(7); - break; - case THURSDAY: - case SATURDAY: - System.out.println(8); - break; - case WEDNESDAY: - System.out.println(9); - break; -} +String result = switch (day) { + case "M", "W", "F" -> "MWF"; + case "T", "TH", "S" -> "TTS"; + default -> { + if(day.isEmpty()) + yield "Please insert a valid day."; + else + yield "Looks like a Sunday."; + } + + }; +System.out.println(result); ``` -_Java 14 enhancements_ +### 预览新特性 + +#### record 关键字 + +简化数据类的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()`,`hashCode()`, `equals()`方法 + +类似于使用 `class` 定义类,同时使用了 lomobok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解 ```java -switch (day) { - case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); - case TUESDAY -> System.out.println(7); - case THURSDAY, SATURDAY -> System.out.println(8); - case WEDNESDAY -> System.out.println(9); +/** + * 这个类具有两个特征 + * 1. 所有成员属性都是final + * 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个) + * 那么这种类就很适合使用record来声明 + */ +final class Rectangle implements Shape { + final double length; + final double width; + + public Rectangle(double length, double width) { + this.length = length; + this.width = width; + } + + double length() { return length; } + double width() { return width; } } +/** + * 1. 使用record声明的类会自动拥有上面类中的三个方法 + * 2. 在这基础上还附赠了equals(),hashCode()方法以及toString()方法 + * 3. toString方法中包括所有成员属性的字符串表示形式及其名称 + */ +record Rectangle(float length, float width) { } ``` -### instanceof 增强 +#### 文本块 + +Java14 中,文本块依然是预览特性,不过,其引入了两个新的转义字符: + +- `\` : 表示行尾,不引入换行符 +- `\s` :表示单个空格 + +```java +String str = "凡心所向,素履所往,生如逆旅,一苇以航。"; + +String str2 = """ + 凡心所向,素履所往, \ + 生如逆旅,一苇以航。"""; +System.out.println(str2);// 凡心所向,素履所往, 生如逆旅,一苇以航。 +String text = """ + java + c++\sphp + """; +System.out.println(text); +//输出: +java +c++ php +``` + +#### instanceof 增强 依然是**预览特性** ,Java 12 新特性中介绍过。 -### 其他特性 +### Java14 其他特性 - 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Window(个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用) -- 移除了 CMS 垃圾收集器(功成而退) +- 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退) - 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`,window 平台下的`msi`和`exe` ## 总结 ### 关于预览特性 -- 先贴一段 oracle 官网原文:`This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.` -- 这是一个预览功能,该功能的设计,规格和实现是完整的,但不是永久性的,这意味着该功能可能以其他形式存在或在将来的 JDK 版本中根本不存在。 要编译和运行包含预览功能的代码,必须指定其他命令行选项。 -- 就以`switch`的增强为例子,从 Java12 中推出,到 Java13 中将继续增强,直到 Java14 才正式转正进入 JDK 可以放心使用,不用考虑后续 JDK 版本对其的改动或修改 -- 一方面可以看出 JDK 作为标准平台在增加新特性的严谨态度,另一方面个人认为是对于预览特性应该采取审慎使用的态度。特性的设计和实现容易,但是其实际价值依然需要在使用中去验证 +先贴一段 oracle 官网原文:`This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.` + +这是一个预览功能,该功能的设计,规格和实现是完整的,但不是永久性的,这意味着该功能可能以其他形式存在或在将来的 JDK 版本中根本不存在。 要编译和运行包含预览功能的代码,必须指定其他命令行选项。 + +就以`switch`的增强为例子,从 Java12 中推出,到 Java13 中将继续增强,直到 Java14 才正式转正进入 JDK 可以放心使用,不用考虑后续 JDK 版本对其的改动或修改 + +一方面可以看出 JDK 作为标准平台在增加新特性的严谨态度,另一方面个人认为是对于预览特性应该采取审慎使用的态度。特性的设计和实现容易,但是其实际价值依然需要在使用中去验证 ### JVM 虚拟机优化 -- 每次 Java 版本的发布都伴随着对 JVM 虚拟机的优化,包括对现有垃圾回收算法的改进,引入新的垃圾回收算法,移除老旧的不再适用于今天的垃圾回收算法等 -- 整体优化的方向是**高效,低时延的垃圾回收表现** -- 对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升** +每次 Java 版本的发布都伴随着对 JVM 虚拟机的优化,包括对现有垃圾回收算法的改进,引入新的垃圾回收算法,移除老旧的不再适用于今天的垃圾回收算法等 + +整体优化的方向是**高效,低时延的垃圾回收表现** + +对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升** -## 参考信息 +## 参考资料 +- JDK Project Overview : - IBM Developer Java9 - Guide to Java10 - Java 10 新特性介绍 @@ -800,4 +823,5 @@ switch (day) { - New Java13 Features - Java13 新特性概述 - Oracle Java14 record -- java14-features \ No newline at end of file +- java14-features +- Java 14 Features : \ No newline at end of file From 7f853ef42f13a3ca7572ee7a6392bf2ab78e98fd Mon Sep 17 00:00:00 2001 From: ObSob <32333557+ObSob@users.noreply.github.com> Date: Thu, 19 Aug 2021 21:44:36 +0800 Subject: [PATCH 17/20] Update zookeeper-plus.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit typo: 应为Atomic --- .../distributed-system/zookeeper/zookeeper-plus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/system-design/distributed-system/zookeeper/zookeeper-plus.md b/docs/system-design/distributed-system/zookeeper/zookeeper-plus.md index 44b5abf6f48..ef37abb3c75 100644 --- a/docs/system-design/distributed-system/zookeeper/zookeeper-plus.md +++ b/docs/system-design/distributed-system/zookeeper/zookeeper-plus.md @@ -184,7 +184,7 @@ ### 5.1. `Zookeeper` 架构 -作为一个优秀高效且可靠的分布式协调框架,`ZooKeeper` 在解决分布式数据一致性问题时并没有直接使用 `Paxos` ,而是专门定制了一致性协议叫做 `ZAB(ZooKeeper Automic Broadcast)` 原子广播协议,该协议能够很好地支持 **崩溃恢复** 。 +作为一个优秀高效且可靠的分布式协调框架,`ZooKeeper` 在解决分布式数据一致性问题时并没有直接使用 `Paxos` ,而是专门定制了一致性协议叫做 `ZAB(ZooKeeper Atomic Broadcast)` 原子广播协议,该协议能够很好地支持 **崩溃恢复** 。 ![Zookeeper架构](https://img-blog.csdnimg.cn/img_convert/0c38d08ea026e25bf3849cc7654a4e79.png) From 1bfc5c14abbaa2571da57e5273176490043aff9f Mon Sep 17 00:00:00 2001 From: guide Date: Fri, 20 Aug 2021 17:07:47 +0800 Subject: [PATCH 18/20] =?UTF-8?q?[feat]Java=2015=20=E6=96=B0=E7=89=B9?= =?UTF-8?q?=E6=80=A7=E6=80=BB=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- ...71\346\200\247\346\200\273\347\273\223.md" | 207 ++++++++++++++---- docs/system-design/naming.md | 93 +++++--- 3 files changed, 230 insertions(+), 72 deletions(-) rename "docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" => "docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md" (90%) diff --git a/README.md b/README.md index eca328cc313..4b4e7557802 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle ### 新特性 1. **Java 8** :[Java 8 新特性总结](docs/java/new-features/Java8新特性总结.md)、[Java8常用新特性总结](docs/java/new-features/java8-common-new-features.md) 、[Java 8 学习资源推荐](docs/java/new-features/Java8教程推荐.md)、[Java8 forEach 指南](docs/java/new-features/Java8foreach指南.md) -2. **Java9~Java14** : [一文带你看遍 JDK9~14 的重要新特性!](./docs/java/new-features/一文带你看遍JDK9到14的重要新特性.md) +2. **Java9~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md) ## 计算机基础 diff --git "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" "b/docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md" similarity index 90% rename from "docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" rename to "docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md" index cb0669f3b32..c815fa1ab7d 100644 --- "a/docs/java/new-features/\344\270\200\346\226\207\345\270\246\344\275\240\347\234\213\351\201\215JDK9\345\210\26014\347\232\204\351\207\215\350\246\201\346\226\260\347\211\271\346\200\247.md" +++ "b/docs/java/new-features/java\346\226\260\347\211\271\346\200\247\346\200\273\347\273\223.md" @@ -336,7 +336,7 @@ var op = Optional.empty(); System.out.println(op.isEmpty());//判断指定的 Optional 对象是否为空 ``` -### ZGC:可伸缩低延迟垃圾收集器 +### ZGC(可伸缩低延迟垃圾收集器) **ZGC 即 Z Garbage Collector**,是一个可伸缩的、低延迟的垃圾收集器。 @@ -549,6 +549,46 @@ if(obj instanceof String str){ ## Java13 +### 增强 ZGC(释放未使用内存) + +在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。 + +ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织。 + +在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。 + +### SocketAPI 重构 + +Java Socket API 终于迎来了重大更新! + +Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 + +并且,在 Java 13 中是默认使用新的 Socket 实现。 + +```java +public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { +} +``` + +### FileSystems + +`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序: + +- `newFileSystem(Path)` +- `newFileSystem(Path, Map)` +- `newFileSystem(Path, Map, ClassLoader)` + +### 动态 CDS 存档 + +Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。 + +这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。 + +```bash +$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar +$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar +``` + ### 预览新特性 #### 文本块 @@ -569,7 +609,6 @@ String json ="{\n" + 支持文本块之后的 HTML 写法: ```java - String json = """ { "name":"mkyong", @@ -633,46 +672,6 @@ public String translateEscapes() { } ``` -### 增强 ZGC(释放未使用内存) - -在 Java 11 中是实验性的引入的 ZGC 在实际的使用中存在未能主动将未使用的内存释放给操作系统的问题。 - -ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages 区域时,它们将被释放并返回到页面缓存 **ZPageCache** 中,此缓存中的 ZPages 按最近最少使用(LRU)的顺序,并按照大小进行组织。 - -在 Java 13 中,ZGC 将向操作系统返回被标识为长时间未使用的页面,这样它们将可以被其他进程重用。 - -### SocketAPI 重构 - -Java Socket API 终于迎来了重大更新! - -Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 - -并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 - -```java -public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { -} -``` - -### FileSystems - -`FileSystems` 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序: - -- `newFileSystem(Path)` -- `newFileSystem(Path, Map)` -- `newFileSystem(Path, Map, ClassLoader)` - -### 动态 CDS 存档 - -Java 13 中对 Java 10 中引入的应用程序类数据共享(AppCDS)进行了进一步的简化、改进和扩展,即:**允许在 Java 应用程序执行结束时动态进行类归档**,具体能够被归档的类包括所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。 - -这提高了应用程序类数据共享([AppCDS](https://openjdk.java.net/jeps/310))的可用性。无需用户进行试运行来为每个应用程序创建类列表。 - -```bash -$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar -$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar -``` - ## Java14 ### 空指针异常精准提示 @@ -789,6 +788,127 @@ c++ php - 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退) - 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`,window 平台下的`msi`和`exe` +## Java15 + +### CharSequence + +`CharSequence` 接口添加了一个默认方法 `isEmpty()` 来判断字符序列为空,如果是则返回 true。 + +```java +public interface CharSequence { + default boolean isEmpty() { + return this.length() == 0; + } +} +``` + +### TreeMap + +`TreeMap` 新引入了下面这些方法: + +- `putIfAbsent()` +- `computeIfAbsent()` +- `computeIfPresent()` +- `compute()` +- `merge()` + +### ZGC(转正) + +Java11 的时候 ,ZGC 还在试验阶段。 + +当时,ZGC 的出现让众多 Java 开发者看到了垃圾回收器的另外一种可能,因此备受关注。 + +经过多个版本的迭代,不断的完善和修复问题,ZGC 在 Java 15 已经可以正式使用了! + +不过,默认的垃圾回收器依然是 G1。你可以通过下面的参数启动 ZGC: + +```bash +$ java -XX:+UseZGC className +``` + +### EdDSA(数字签名算法) + +新加入了一个安全性和性能都更强的基于 Edwards-Curve Digital Signature Algorithm (EdDSA)实现的数字签名算法。 + +虽然其性能优于现有的 ECDSA 实现,不过,它并不会完全取代 JDK 中现有的椭圆曲线数字签名算法( ECDSA)。 + +```java +KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519"); +KeyPair kp = kpg.generateKeyPair(); + +byte[] msg = "test_string".getBytes(StandardCharsets.UTF_8); + +Signature sig = Signature.getInstance("Ed25519"); +sig.initSign(kp.getPrivate()); +sig.update(msg); +byte[] s = sig.sign(); + +String encodedString = Base64.getEncoder().encodeToString(s); +System.out.println(encodedString); +``` + +输出: + +``` +0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg== +``` + +### 文本块(转正) + +在 Java 15 ,文本块是正式的功能特性了。 + +### 隐藏类(Hidden Classes) + +隐藏类是为框架(frameworks)所设计的,隐藏类不能直接被其他类的字节码使用,只能在运行时生成类并通过反射间接使用它们。 + +### 预览新特性 + +#### record 关键字 + +Java 15 对 Java 14 中引入的预览新特性进行了增强,主要是引入了一个新的概念 **密封类(Sealed Classes)。** + +密封类可以对继承或者实现它们的类进行限制。 + +比如抽象类 `Person` 只允许 `Employee` 和 `Manager` 继承。 + +```java +public abstract sealed class Person + permits Employee, Manager { + + //... +} +``` + +另外,任何扩展密封类的类本身都必须声明为 `sealed`、`non-sealed` 或 `final`。 + +```java +public final class Employee extends Person { +} + +public non-sealed class Manager extends Person { +} +``` + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/javaguide/image-20210820153955587.png) + +在 `java.lang.Class` 增加了两个公共方法用于获取 `Record` 类信息: + +1. `RecordComponent[] getRecordComponents()` +2. `boolean isRecord()` + +#### instanceof 模式匹配 + +Java 15 并没有对此特性进行调整,继续预览特性,主要用于接受更多的使用反馈。 + +在未来的 Java 版本中,Java 的目标是继续完善 `instanceof` 模式匹配新特性。 + +### Java15 其他新特性 + +- **Nashorn JavaScript 引擎彻底移除** :Nashorn 从 Java8 开始引入的 JavaScript 引擎,Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性。在 Java 11 中就已经被弃用,到了 Java 15 就彻底被删除了。 +- **DatagramSocket API 重构** +- **禁用和废弃偏向锁(Biased Locking)** : 偏向锁的引入增加了 JVM 的复杂性大于其带来的性能提升。不过,你仍然可以使用 `-XX:+UseBiasedLocking` 启用偏向锁定,但它会提示 这是一个已弃用的 API。 +- ...... + ## 总结 ### 关于预览特性 @@ -824,4 +944,5 @@ c++ php - Java13 新特性概述 - Oracle Java14 record - java14-features -- Java 14 Features : \ No newline at end of file +- Java 14 Features : +- What is new in Java 15: https://mkyong.com/java/what-is-new-in-java-15/ \ No newline at end of file diff --git a/docs/system-design/naming.md b/docs/system-design/naming.md index 33d0db49286..33579c9160c 100644 --- a/docs/system-design/naming.md +++ b/docs/system-design/naming.md @@ -1,14 +1,42 @@ -编程过程中,有太多太多让我们头疼的事情了,比如命名、维护其他人的代码、写测试、与其他人沟通交流等等。就连世界级软件大师 **Martin Fowler** 大神都说过 CS 领域有两大最难的事情,一是**缓存失效**,一是**程序命名**(@ [https://martinfowler.com/bliki/TwoHardThings.html](https://martinfowler.com/bliki/TwoHardThings.html))。 +> 可选标题:工作半年,变量命名不规范,被diss了! +> +> 项目组新来的实习生因为变量命名被 “diss” 了! + +大家好,这里是热爱分享的 Guide ! + +我还记得我刚工作那一段时间, 项目 Code Review 的时候,我经常因为变量命名不规范而被 “diss”! + +究其原因还是自己那会经验不足,而且,大学那会写项目的时候不太注意这些问题,想着只要把功能实现出来就行了。 + +但是,工作中就不一样,为了代码的可读性、可维护性,项目组对于代码质量的要求还是很高的! + +前段时间,项目组新来的一个实习生也经常在 Code Review 因为变量命名不规范而被 “diss”,这让我想到自己刚到公司写代码那会的日子。 + +于是,我就简单写了这篇关于变量命名规范的文章,希望能对同样有此困扰的小伙伴提供一些帮助。 -![](pictures/marting-naming.png) +确实,编程过程中,有太多太多让我们头疼的事情了,比如命名、维护其他人的代码、写测试、与其他人沟通交流等等。 -今天 Guide 就单独拎出 “**命名**” 来聊聊,据说之前在 Quora 网站,由接近 5000 名程序员票选出来的最难的事情就是“命名”。 +据说之前在 Quora 网站,由接近 5000 名程序员票选出来的最难的事情就是“命名”。 + +大名鼎鼎的《重构》的作者老马(Martin Fowler)曾经在[TwoHardThings](https://martinfowler.com/bliki/TwoHardThings.html)这篇文章中提到过CS 领域有两大最难的事情:一是 **缓存失效** ,一是 **程序命名** 。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/marting-naming.png) + +这个句话实际上也是老马引用别人的,类似的表达还有很多。比如分布式系统领域有两大最难的事情:一是 **保证消息顺序** ,一是 **严格一次传递** 。 + +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/20210629104844645.png) + +今天咱们就单独拎出 “**命名**” 来聊聊! 这篇文章配合我之前发的 [《编码 5 分钟,命名 2 小时?史上最全的 Java 命名规范参考!》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486449&idx=1&sn=c3b502529ff991c7180281bcc22877af&chksm=cea2443af9d5cd2c1c87049ed15ccf6f88275419c7dbe542406166a703b27d0f3ecf2af901f8&token=999884676&lang=zh_CN#rd) 这篇文章阅读效果更佳哦! ## 为什么需要重视命名? -**好的命名即是注释,别人一看到你的命名就知道你的变量、方法或者类是做什么的!** 好的命名对于其他人(包括你自己)理解你的代码有着很大的帮助! +咱们需要先搞懂为什么要重视编程中的命名这一行为,它对于我们的编码工作有着什么意义。 + +**为什么命名很重要呢?** 这是因为 **好的命名即是注释,别人一看到你的命名就知道你的变量、方法或者类是做什么的!** + +简单来说就是 **别人根据你的命名就能知道你的代码要表达的意思** (不过,前提这个人也要有基本的英语知识,对于一些编程中常见的单词比较熟悉)。 简单举个例子说明一下命名的重要性。 @@ -64,7 +92,9 @@ serviceDiscovery、Serviceinstance、LRUCacheFactory 正例: ```java -getUserInfo()、createCustomThreadPool()、setNameFormat(String nameFormat) +getUserInfo() +createCustomThreadPool() +setNameFormat(String nameFormat) Uservice userService; ``` @@ -81,7 +111,9 @@ Uservice user_service 在蛇形命名法中,各个单词之间通过下划线“\_”连接,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。 -蛇形命名法的优势是命名所需要的单词比较多的时候,比如我把上面的命名通过小驼峰命名法给大家看一下:“shouldGet200StatusCodoWhenRequestIsValid”。**感觉如何? 相比于使用蛇形命名法(snake_case)来说是不是不那么易读?\*\*** +蛇形命名法的优势是命名所需要的单词比较多的时候,比如我把上面的命名通过小驼峰命名法给大家看一下:“shouldGet200StatusCodoWhenRequestIsValid”。 + +感觉如何? 相比于使用蛇形命名法(snake_case)来说是不是不那么易读? 正例: @@ -103,29 +135,29 @@ void shouldGet200StatusCodoWhenRequestIsValid() { ### 串式命名法(kebab-case) -在串式命名法中,各个单词之间通过下划线“-”连接,比如`dubbo-registry`。 +在串式命名法中,各个单词之间通过连接符“-”连接,比如`dubbo-registry`。 建议项目文件夹名称使用串式命名法(kebab-case),比如 dubbo 项目的各个模块的命名是下面这样的。 -![](./pictures/dubbo-naming.png) +![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/dubbo-naming.png) ## 常见命名规范 ### Java 语言基本命名规范 -**1.类名需要使用大驼峰命名法(UpperCamelCase)风格。方法名、参数名、成员变量、局部变量需要使用小驼峰命名法(lowerCamelCase)。** +**1、类名需要使用大驼峰命名法(UpperCamelCase)风格。方法名、参数名、成员变量、局部变量需要使用小驼峰命名法(lowerCamelCase)。** -**2.测试方法名、常量、枚举名称需要使用蛇形命名法(snake_case)**,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。并且,**测试方法名称要求全部小写,常量以及枚举名称需要全部大写。** +**2、测试方法名、常量、枚举名称需要使用蛇形命名法(snake_case)**,比如`should_get_200_status_code_when_request_is_valid`、`CLIENT_CONNECT_SERVER_FAILURE`。并且,**测试方法名称要求全部小写,常量以及枚举名称需要全部大写。** -**3.项目文件夹名称使用串式命名法(kebab-case),比如`dubbo-registry`。** +**3、项目文件夹名称使用串式命名法(kebab-case),比如`dubbo-registry`。** -**4.包名统一使用小写,尽量使用单个名词作为包名,各个单词通过 "." 分隔符连接,并且各个单词必须为单数。** +**4、包名统一使用小写,尽量使用单个名词作为包名,各个单词通过 "." 分隔符连接,并且各个单词必须为单数。** 正例: `org.apache.dubbo.common.threadlocal` 反例: ~~`org.apache_dubbo.Common.threadLocals`~~ -**5.抽象类命名使用 Abstract 开头**。 +**5、抽象类命名使用 Abstract 开头**。 ```java //为远程传输部分抽象出来的一个抽象类(出处:Dubbo源码) @@ -134,7 +166,7 @@ public abstract class AbstractClient extends AbstractEndpoint implements Client } ``` -**6.异常类命名使用 Exception 结尾。** +**6、异常类命名使用 Exception 结尾。** ```java //自定义的 NoSuchMethodException(出处:Dubbo源码) @@ -151,7 +183,7 @@ public class NoSuchMethodException extends RuntimeException { } ``` -**7.测试类命名以它要测试的类的名称开始,以 Test 结尾。** +**7、测试类命名以它要测试的类的名称开始,以 Test 结尾。** ```java //为 AnnotationUtils 类写的测试类(出处:Dubbo源码) @@ -166,19 +198,19 @@ POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架 ### 命名易读性规范 -**1.为了能让命名更加易懂和易读,尽量不要缩写/简写单词,除非这些单词已经被公认可以被这样缩写/简写。比如 `CustomThreadFactory` 不可以被写成 ~~`CustomTF` 。** +**1、为了能让命名更加易懂和易读,尽量不要缩写/简写单词,除非这些单词已经被公认可以被这样缩写/简写。比如 `CustomThreadFactory` 不可以被写成 ~~`CustomTF` 。** -**2.命名不像函数一样要尽量追求短,可读性强的名字优先于简短的名字,虽然可读性强的名字会比较长一点。** 这个对应我们上面说的第 1 点。 +**2、命名不像函数一样要尽量追求短,可读性强的名字优先于简短的名字,虽然可读性强的名字会比较长一点。** 这个对应我们上面说的第 1 点。 -**3.避免无意义的命名,你起的每一个名字都要能表明意思。** +**3、避免无意义的命名,你起的每一个名字都要能表明意思。** 正例:`UserService userService;` `int userCount`; 反例: ~~`UserService service`~~ ~~`int count`~~ -**4.避免命名过长(50 个字符以内最好),过长的命名难以阅读并且丑陋。** +**4、避免命名过长(50 个字符以内最好),过长的命名难以阅读并且丑陋。** -5.**不要使用拼音,更不要使用中文。** 注意:像 alibaba 、wuhan、taobao 这种国际通用名词可以当做英文来看待。 +**5、不要使用拼音,更不要使用中文。** 不过像 alibaba 、wuhan、taobao 这种国际通用名词可以当做英文来看待。 正例:discount @@ -186,7 +218,7 @@ POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架 ## Codelf:变量命名神器? -这是一个由国人开发的网站,网上有很多人称其为变量命名神器, Guide 在实际使用了几天之后感觉没那么好用。小伙伴们可以自行体验一下,然后再给出自己的判断。 +这是一个由国人开发的网站,网上有很多人称其为变量命名神器, 我在实际使用了几天之后感觉没那么好用。小伙伴们可以自行体验一下,然后再给出自己的判断。 Codelf 提供了在线网站版本,网址:[https://unbug.github.io/codelf/](https://unbug.github.io/codelf/),具体使用情况如下: @@ -198,17 +230,22 @@ Codelf 提供了在线网站版本,网址:[https://unbug.github.io/codelf/]( ![](pictures/vscode-codelf.png) -## 总结 - -Guide 制作了一个涵盖上面所有重要内容的思维导图,便于小伙伴们日后查阅。 - -![](pictures/naming-mindmap.png) - -## 其他推荐阅读 +## 相关阅读推荐 1. 《阿里巴巴 Java 开发手册》 2. 《Clean Code》 3. Google Java 代码指南:https://google.github.io/styleguide/javaguide.html#s5.1-identifier-name 4. 告别编码5分钟,命名2小时!史上最全的Java命名规范参考:https://www.cnblogs.com/liqiangchn/p/12000361.html +## 总结 + +作为一个合格的程序员,小伙伴们应该都知道代码表义的重要性。想要写出高质量代码,好的命名就是第一步! + +好的命名对于其他人(包括你自己)理解你的代码有着很大的帮助!你的代码越容易被理解,可维护性就越强,侧面也就说明你的代码设计的也就越好! + +在日常编码过程中,我们需要谨记常见命名规范比如类名需要使用大驼峰命名法、不要使用拼音,更不要使用中文......。 + +另外,国人开发的一个叫做 Codelf 的网站被很多人称为“变量命名神器”,当你为命名而头疼的时候,你可以去参考一下上面提供的一些命名示例。 + +最后,祝愿大家都不用再为命名而困扰! From d535742fe36641d5e86eaba6de88b5ddabe2111c Mon Sep 17 00:00:00 2001 From: guide Date: Sat, 21 Aug 2021 20:36:58 +0800 Subject: [PATCH 19/20] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b4e7557802..8e2148994e9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -👉 如果你不知道该学习什么的话,请看 [Java 学习线路图是怎样的?]( https://zhuanlan.zhihu.com/p/379041500) (原创不易,欢迎点赞),这是 2021 最新最完善的 Java 学习路线!另外,我整理了一份各个技术的学习路线,需要的小伙伴[加我微信](#联系我)备注“**Github-学习路线**”即可! +👉 如果你不知道该学习什么的话,请看 [Java 学习线路图是怎样的?]( https://zhuanlan.zhihu.com/p/379041500) (原创不易,欢迎点赞),这是 2021 最新最完善的 Java 学习路线!另外,[我的朋友整理了一份消息队列常见面试题,需要的小伙伴可以点击领取!](http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100025985&idx=1&sn=681af486050fabbeea27fa1c3bec5d65&chksm=4ea1e94a79d6605c72f280b5268100c6e96c6ab1dc9a0178b33e25a72ff5f4eac3dcb56fa44f#rd) 👉 推荐 [在线阅读](https://snailclimb.gitee.io/javaguide) (Github 访问速度比较慢可能会导致部分图片无法刷新出来) From 2cc2d9a969505163c293efa52b48b3c045c15ce3 Mon Sep 17 00:00:00 2001 From: guide Date: Mon, 23 Aug 2021 12:01:00 +0800 Subject: [PATCH 20/20] =?UTF-8?q?[refractor&feat]=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=AE=8C=E5=96=84&=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=B9=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 56 +++--- ...62\347\256\227\346\263\225\351\242\230.md" | 0 ...50\347\256\227\346\263\225\351\242\230.md" | 0 ...06\347\274\226\347\250\213\351\242\230.md" | 0 .../data-structure/bloom-filter.md | 45 ++--- .../pictures/\345\233\276/\345\233\276.png" | Bin ...5\205\210\346\220\234\347\264\2421.drawio" | 0 ...\345\205\210\346\220\234\347\264\2421.png" | Bin ...5\205\210\346\220\234\347\264\2422.drawio" | 0 ...\345\205\210\346\220\234\347\264\2422.png" | Bin ...5\205\210\346\220\234\347\264\2423.drawio" | 0 ...\345\205\210\346\220\234\347\264\2423.png" | Bin ...5\205\210\346\220\234\347\264\2424.drawio" | 0 ...\345\205\210\346\220\234\347\264\2424.png" | Bin ...5\205\210\346\220\234\347\264\2425.drawio" | 0 ...\345\205\210\346\220\234\347\264\2425.png" | Bin ...5\205\210\346\220\234\347\264\2426.drawio" | 0 ...\345\205\210\346\220\234\347\264\2426.png" | Bin ...47\264\242\345\233\276\347\244\272.drawio" | 0 ...4\347\264\242\345\233\276\347\244\272.png" | Bin ...51\230\265\345\255\230\345\202\250.drawio" | 0 ...1\351\230\265\345\255\230\345\202\250.png" | Bin ...50\241\250\345\255\230\345\202\250.drawio" | 0 ...5\350\241\250\345\255\230\345\202\250.png" | Bin ...51\230\265\345\255\230\345\202\250.drawio" | 0 ...1\351\230\265\345\255\230\345\202\250.png" | Bin ...47\232\204\345\211\257\346\234\254.drawio" | 0 ...50\241\250\345\255\230\345\202\250.drawio" | 0 ...5\350\241\250\345\255\230\345\202\250.png" | Bin ...5\205\210\346\220\234\347\264\2421.drawio" | 0 ...\345\205\210\346\220\234\347\264\2421.png" | Bin ...5\205\210\346\220\234\347\264\2422.drawio" | 0 ...\345\205\210\346\220\234\347\264\2422.png" | Bin ...5\205\210\346\220\234\347\264\2423.drawio" | 0 ...\345\205\210\346\220\234\347\264\2423.png" | Bin ...5\205\210\346\220\234\347\264\2424.drawio" | 0 ...\345\205\210\346\220\234\347\264\2424.png" | Bin ...5\205\210\346\220\234\347\264\2425.drawio" | 0 ...\345\205\210\346\220\234\347\264\2425.png" | Bin ...5\205\210\346\220\234\347\264\2426.drawio" | 0 ...\345\205\210\346\220\234\347\264\2426.png" | Bin ...47\264\242\345\233\276\347\244\272.drawio" | 0 ...4\347\264\242\345\233\276\347\244\272.png" | Bin ...\351\241\266\345\205\203\347\264\2401.png" | Bin ...\351\241\266\345\205\203\347\264\2402.png" | Bin ...\351\241\266\345\205\203\347\264\2403.png" | Bin ...\351\241\266\345\205\203\347\264\2404.png" | Bin ...\351\241\266\345\205\203\347\264\2405.png" | Bin ...\351\241\266\345\205\203\347\264\2406.png" | Bin ...\345\205\245\345\205\203\347\264\2401.png" | Bin ...\345\205\245\345\205\203\347\264\2402.png" | Bin ...\345\205\245\345\205\203\347\264\2403.png" | Bin .../pictures/\345\240\206/\345\240\2061.png" | Bin .../pictures/\345\240\206/\345\240\2062.png" | Bin ...\345\240\206\346\216\222\345\272\2171.png" | Bin ...\345\240\206\346\216\222\345\272\2172.png" | Bin ...\345\240\206\346\216\222\345\272\2173.png" | Bin ...\345\240\206\346\216\222\345\272\2174.png" | Bin ...\345\240\206\346\216\222\345\272\2175.png" | Bin ...\345\240\206\346\216\222\345\272\2176.png" | Bin ...6\347\232\204\345\255\230\345\202\250.png" | Bin .../\345\273\272\345\240\2061.png" | Bin .../\345\273\272\345\240\2062.png" | Bin .../\345\273\272\345\240\2063.png" | Bin .../\345\273\272\345\240\2064.png" | Bin ...45\272\217\351\201\215\345\216\206.drawio" | 1 + ...5\345\272\217\351\201\215\345\216\206.png" | Bin 0 -> 35285 bytes ...5\272\217\351\201\215\345\216\2062.drawio" | 1 + ...\345\272\217\351\201\215\345\216\2062.png" | Bin 0 -> 11447 bytes ...45\272\217\351\201\215\345\216\206.drawio" | 1 + ...0\345\272\217\351\201\215\345\216\206.png" | Bin 0 -> 35364 bytes ...45\272\217\351\201\215\345\216\206.drawio" | 1 + ...6\345\272\217\351\201\215\345\216\206.png" | Bin 0 -> 35267 bytes ...44\272\214\345\217\211\346\240\221.drawio" | 1 + ...0\344\272\214\345\217\211\346\240\221.png" | Bin 0 -> 28497 bytes ...44\272\214\345\217\211\346\240\221.drawio" | 1 + ...1\344\272\214\345\217\211\346\240\221.png" | Bin 0 -> 20533 bytes .../\346\226\234\346\240\221.drawio" | 1 + .../\346\226\234\346\240\221.png" | Bin 0 -> 20671 bytes ...44\272\214\345\217\211\346\240\221.drawio" | 1 + ...1\344\272\214\345\217\211\346\240\221.png" | Bin 0 -> 20027 bytes ...44\272\214\345\217\211\346\240\221.drawio" | 1 + ...0\344\272\214\345\217\211\346\240\221.png" | Bin 0 -> 22043 bytes ...45\272\217\345\255\230\345\202\250.drawio" | 1 + ...2\345\272\217\345\255\230\345\202\250.png" | Bin 0 -> 47860 bytes ...5\272\217\345\255\230\345\202\2502.drawio" | 1 + ...\345\272\217\345\255\230\345\202\2502.png" | Bin 0 -> 54408 bytes ...\345\215\225\351\223\276\350\241\2502.png" | Bin ...2\347\216\257\351\223\276\350\241\250.png" | Bin ...4\345\220\221\351\223\276\350\241\250.png" | Bin ...\345\210\227-\345\240\206\346\273\241.png" | Bin .../\346\225\260\347\273\204.png" | Bin .../\346\240\210.png" | Bin ...45\222\214\345\211\215\350\277\233.drawio" | 0 ...0\345\222\214\345\211\215\350\277\233.png" | Bin .../\351\230\237\345\210\227.png" | Bin ...7\345\201\207\346\272\242\345\207\272.png" | Bin .../cs-basics/data-structure/\345\233\276.md" | 0 .../cs-basics/data-structure/\345\240\206.md" | 3 + .../cs-basics/data-structure/\346\240\221.md" | 174 +++++++++++++++++ .../\347\272\242\351\273\221\346\240\221.md" | 14 ++ ...60\346\215\256\347\273\223\346\236\204.md" | 0 .../HTTPS\344\270\255\347\232\204TLS.md" | 0 .../network/images/Cut-Trough-Switching_0.gif | Bin docs/{ => cs-basics}/network/images/isp.png | Bin ...3\347\273\223\346\236\204\345\233\276.png" | Bin .../\344\274\240\350\276\223\345\261\202.png" | Bin .../\345\272\224\347\224\250\345\261\202.png" | Bin ...6\351\223\276\350\267\257\345\261\202.png" | Bin .../\347\211\251\347\220\206\345\261\202.png" | Bin .../\347\275\221\347\273\234\345\261\202.png" | Bin ...5\344\275\234\345\267\245\347\250\213.png" | Bin ...27\346\234\272\347\275\221\347\273\234.md" | 0 ...45\350\257\206\346\200\273\347\273\223.md" | 0 .../{ => cs-basics}/operating-system/Shell.md | 0 .../{ => cs-basics}/operating-system/basis.md | 0 .../operating-system/images/Linux-Logo.png | Bin .../images/Linux\344\271\213\347\210\266.png" | Bin ...3\351\231\220\345\221\275\344\273\244.png" | Bin ...3\351\231\220\350\247\243\350\257\273.png" | Bin ...x\347\233\256\345\275\225\346\240\221.png" | Bin .../operating-system/images/linux.png | Bin .../operating-system/images/macos.png | Bin .../operating-system/images/unix.png | Bin .../operating-system/images/windows.png | Bin ...7\344\273\266\346\235\203\351\231\220.png" | Bin ...\273\266inode\344\277\241\346\201\257.png" | Bin ...6\345\206\205\346\240\270\346\200\201.png" | Bin .../{ => cs-basics}/operating-system/linux.md | 0 ...60\346\215\256\347\273\223\346\236\204.md" | 179 ------------------ ...\217\215\347\274\226\350\257\221tricks.md" | 90 ++++----- ...47\350\203\275\351\227\256\351\242\230.md" | 160 ++++++++-------- 132 files changed, 376 insertions(+), 356 deletions(-) rename "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" => "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" (100%) rename "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" => "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" (100%) rename "docs/dataStructures-algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" => "docs/cs-basics/algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" (100%) rename docs/{dataStructures-algorithms => cs-basics}/data-structure/bloom-filter.md (74%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\233\276.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\233\276.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" => "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2061.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2061.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2062.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2062.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" => "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" (100%) create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\220\216\345\272\217\351\201\215\345\216\206.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\256\214\345\205\250\344\272\214\345\217\211\346\240\221.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\346\226\234\346\240\221.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\346\273\241\344\272\214\345\217\211\346\240\221.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\223\276\345\274\217\345\255\230\345\202\250\344\272\214\345\217\211\346\240\221.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\250.png" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.drawio" create mode 100644 "docs/cs-basics/data-structure/pictures/\346\240\221/\351\241\272\345\272\217\345\255\230\345\202\2502.png" rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\215\225\351\223\276\350\241\2502.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\345\276\252\347\216\257\351\223\276\350\241\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\217\214\345\220\221\351\223\276\350\241\250.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\345\276\252\347\216\257\351\230\237\345\210\227-\345\240\206\346\273\241.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\225\260\347\273\204.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.drawio" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\346\240\210\345\256\236\347\216\260\346\265\217\350\247\210\345\231\250\345\200\222\351\200\200\345\222\214\345\211\215\350\277\233.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\230\237\345\210\227.png" (100%) rename "docs/dataStructures-algorithms/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png" => "docs/cs-basics/data-structure/pictures/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204/\351\241\272\345\272\217\351\230\237\345\210\227\345\201\207\346\272\242\345\207\272.png" (100%) rename "docs/dataStructures-algorithms/data-structure/\345\233\276.md" => "docs/cs-basics/data-structure/\345\233\276.md" (100%) rename "docs/dataStructures-algorithms/data-structure/\345\240\206.md" => "docs/cs-basics/data-structure/\345\240\206.md" (99%) create mode 100644 "docs/cs-basics/data-structure/\346\240\221.md" create mode 100644 "docs/cs-basics/data-structure/\347\272\242\351\273\221\346\240\221.md" rename "docs/dataStructures-algorithms/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md" => "docs/cs-basics/data-structure/\347\272\277\346\200\247\346\225\260\346\215\256\347\273\223\346\236\204.md" (100%) rename "docs/network/HTTPS\344\270\255\347\232\204TLS.md" => "docs/cs-basics/network/HTTPS\344\270\255\347\232\204TLS.md" (100%) rename docs/{ => cs-basics}/network/images/Cut-Trough-Switching_0.gif (100%) rename docs/{ => cs-basics}/network/images/isp.png (100%) rename "docs/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png" => "docs/cs-basics/network/images/\344\270\203\345\261\202\344\275\223\347\263\273\347\273\223\346\236\204\345\233\276.png" (100%) rename "docs/network/images/\344\274\240\350\276\223\345\261\202.png" => "docs/cs-basics/network/images/\344\274\240\350\276\223\345\261\202.png" (100%) rename "docs/network/images/\345\272\224\347\224\250\345\261\202.png" => "docs/cs-basics/network/images/\345\272\224\347\224\250\345\261\202.png" (100%) rename "docs/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png" => "docs/cs-basics/network/images/\346\225\260\346\215\256\351\223\276\350\267\257\345\261\202.png" (100%) rename "docs/network/images/\347\211\251\347\220\206\345\261\202.png" => "docs/cs-basics/network/images/\347\211\251\347\220\206\345\261\202.png" (100%) rename "docs/network/images/\347\275\221\347\273\234\345\261\202.png" => "docs/cs-basics/network/images/\347\275\221\347\273\234\345\261\202.png" (100%) rename "docs/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png" => "docs/cs-basics/network/images/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\347\202\271\346\200\273\347\273\223/\344\270\207\347\273\264\347\275\221\347\232\204\345\244\247\350\207\264\345\267\245\344\275\234\345\267\245\347\250\213.png" (100%) rename "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" => "docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234.md" (100%) rename "docs/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md" => "docs/cs-basics/network/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\347\237\245\350\257\206\346\200\273\347\273\223.md" (100%) rename docs/{ => cs-basics}/operating-system/Shell.md (100%) rename docs/{ => cs-basics}/operating-system/basis.md (100%) rename docs/{ => cs-basics}/operating-system/images/Linux-Logo.png (100%) rename "docs/operating-system/images/Linux\344\271\213\347\210\266.png" => "docs/cs-basics/operating-system/images/Linux\344\271\213\347\210\266.png" (100%) rename "docs/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png" => "docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\345\221\275\344\273\244.png" (100%) rename "docs/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png" => "docs/cs-basics/operating-system/images/Linux\346\235\203\351\231\220\350\247\243\350\257\273.png" (100%) rename "docs/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png" => "docs/cs-basics/operating-system/images/Linux\347\233\256\345\275\225\346\240\221.png" (100%) rename docs/{ => cs-basics}/operating-system/images/linux.png (100%) rename docs/{ => cs-basics}/operating-system/images/macos.png (100%) rename docs/{ => cs-basics}/operating-system/images/unix.png (100%) rename docs/{ => cs-basics}/operating-system/images/windows.png (100%) rename "docs/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png" => "docs/cs-basics/operating-system/images/\344\277\256\346\224\271\346\226\207\344\273\266\346\235\203\351\231\220.png" (100%) rename "docs/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png" => "docs/cs-basics/operating-system/images/\346\226\207\344\273\266inode\344\277\241\346\201\257.png" (100%) rename "docs/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png" => "docs/cs-basics/operating-system/images/\347\224\250\346\210\267\346\200\201\344\270\216\345\206\205\346\240\270\346\200\201.png" (100%) rename docs/{ => cs-basics}/operating-system/linux.md (100%) delete mode 100644 "docs/dataStructures-algorithms/\346\225\260\346\215\256\347\273\223\346\236\204.md" rename "docs/java/JAD\345\217\215\347\274\226\350\257\221tricks.md" => "docs/java/tips/JAD\345\217\215\347\274\226\350\257\221tricks.md" (68%) rename "docs/java/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\232\344\275\215\345\270\270\350\247\201Java\346\200\247\350\203\275\351\227\256\351\242\230.md" => "docs/java/tips/\346\211\213\346\212\212\346\211\213\346\225\231\344\275\240\345\256\232\344\275\215\345\270\270\350\247\201Java\346\200\247\350\203\275\351\227\256\351\242\230.md" (54%) diff --git a/README.md b/README.md index 8e2148994e9..786e0ccf6d9 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ ### 基础 -**知识点/面试题:**(必看:+1: ) +**知识点/面试题** : (必看:+1: ) 1. **[Java 基础知识](docs/java/basis/Java基础知识.md)** 2. **[Java 基础知识疑难点/易错点](docs/java/basis/Java基础知识疑难点.md)** @@ -71,11 +71,11 @@ **重要知识点详解:** -2. **线程池**:[Java 线程池学习总结](./docs/java/multi-thread/java线程池学习总结.md)、[拿来即用的线程池最佳实践](./docs/java/multi-thread/拿来即用的线程池最佳实践.md) -4. [ ThreadLocal 关键字解析](docs/java/multi-thread/万字详解ThreadLocal关键字.md) -5. [并发容器总结](docs/java/multi-thread/并发容器总结.md) -6. [JUC 中的 Atomic 原子类总结](docs/java/multi-thread/Atomic原子类总结.md) -7. [AQS 原理以及 AQS 同步组件总结](docs/java/multi-thread/AQS原理以及AQS同步组件总结.md) +1. **线程池**:[Java 线程池学习总结](./docs/java/multi-thread/java线程池学习总结.md)、[拿来即用的线程池最佳实践](./docs/java/multi-thread/拿来即用的线程池最佳实践.md) +2. [ ThreadLocal 关键字解析](docs/java/multi-thread/万字详解ThreadLocal关键字.md) +3. [并发容器总结](docs/java/multi-thread/并发容器总结.md) +4. [JUC 中的 Atomic 原子类总结](docs/java/multi-thread/Atomic原子类总结.md) +5. [AQS 原理以及 AQS 同步组件总结](docs/java/multi-thread/AQS原理以及AQS同步组件总结.md) ### JVM (必看 :+1:) @@ -95,28 +95,38 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle 1. **Java 8** :[Java 8 新特性总结](docs/java/new-features/Java8新特性总结.md)、[Java8常用新特性总结](docs/java/new-features/java8-common-new-features.md) 、[Java 8 学习资源推荐](docs/java/new-features/Java8教程推荐.md)、[Java8 forEach 指南](docs/java/new-features/Java8foreach指南.md) 2. **Java9~Java15** : [一文带你看遍 JDK9~15 的重要新特性!](./docs/java/new-features/java新特性总结.md) +### 小技巧 + +1. [JAD 反编译](docs/java/tips/JAD反编译tricks.md) +2. [手把手教你定位常见 Java 性能问题](./docs/java/tips/手把手教你定位常见Java性能问题.md) + ## 计算机基础 👉 **[图解计算机基础 PDF 下载](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=100021725&idx=1&sn=2db9664ca25363139a81691043e9fd8f&chksm=4ea19a1679d61300d8990f7e43bfc7f476577a81b712cf0f9c6f6552a8b219bc081efddb5c54#rd)** 。 ### 操作系统 -1. [操作系统常见问题总结!](docs/operating-system/basis.md) -2. [后端程序员必备的 Linux 基础知识](docs/operating-system/linux.md) -3. [Shell 编程入门](docs/operating-system/Shell.md) +1. [操作系统常见问题总结!](docs/cs-basics/operating-system/basis.md) +2. [后端程序员必备的 Linux 基础知识总结](docs/cs-basics/operating-system/linux.md) +3. [Shell 编程入门](docs/cs-basics/operating-system/Shell.md) ### 网络 -1. [计算机网络常见面试题](docs/network/计算机网络.md) -2. [计算机网络基础知识总结](docs/network/计算机网络知识总结.md) +1. [计算机网络常见面试题](docs/cs-basics/network/计算机网络.md) +2. [计算机网络基础知识总结](docs/cs-basics/network/计算机网络知识总结.md) ### 数据结构 -- **图解数据结构:** - 1. [线性数据结构 :数组、链表、栈、队列](docs/dataStructures-algorithms/data-structure/线性数据结构.md) - 2. [图](docs/dataStructures-algorithms/data-structure/图.md) - 3. [堆](docs/dataStructures-algorithms/data-structure/堆.md) -- [不了解布隆过滤器?一文给你整的明明白白!](docs/dataStructures-algorithms/data-structure/bloom-filter.md) +**图解数据结构:** + +1. [线性数据结构 :数组、链表、栈、队列](docs/cs-basics/data-structure/线性数据结构.md) +2. [图](docs/cs-basics/data-structure/图.md) +3. [堆](docs/cs-basics/data-structure/堆.md) +4. [树](docs/cs-basics/data-structure/树.md) :重点关注[红黑树](docs/cs-basics/data-structure/红黑树.md)、B-,B+,B*树、LSM树 + +其他常用数据结构 : + +1. [布隆过滤器](docs/cs-basics/data-structure/bloom-filter.md) ### 算法 @@ -125,11 +135,13 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle - [算法学习书籍+资源推荐](https://www.zhihu.com/question/323359308/answer/1545320858) 。 - [如何刷Leetcode?](https://www.zhihu.com/question/31092580/answer/1534887374) -**常见算法问题总结:** +**常见算法问题总结** : + +- [几道常见的字符串算法题总结 ](docs/cs-basics/algorithms/几道常见的字符串算法题.md) +- [几道常见的链表算法题总结 ](docs/cs-basics/algorithms/几道常见的链表算法题.md) +- [剑指 offer 部分编程题](docs/cs-basics/algorithms/剑指offer部分编程题.md) -- [几道常见的字符串算法题总结 ](docs/dataStructures-algorithms/几道常见的字符串算法题.md) -- [几道常见的链表算法题总结 ](docs/dataStructures-algorithms/几道常见的链表算法题.md) -- [剑指 offer 部分编程题](docs/dataStructures-algorithms/剑指offer部分编程题.md) +另外,[GeeksforGeeks]( https://www.geeksforgeeks.org/fundamentals-of-algorithms/) 这个网站总结了常见的算法 ,比较全面系统。 ## 数据库 @@ -354,7 +366,6 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读: ## 工具 -1. **Java** :[JAD 反编译](docs/java/JAD反编译tricks.md)、[手把手教你定位常见 Java 性能问题](./docs/java/手把手教你定位常见Java性能问题.md) 2. **Git** :[Git 入门](docs/tools/Git.md) 3. **Github** : [Github小技巧](docs/tools/Github技巧.md) 4. **Docker** : [Docker 基本概念解读](docs/tools/Docker.md) 、[Docker从入门到上手干事](docs/tools/Docker从入门到实战.md) @@ -378,7 +389,8 @@ Dubbo 是一款国产的 RPC 框架,由阿里开源。相关阅读: ### 待办 -- [ ] 数据结构总结重构 +- [ ] 计算机网络知识点完善 +- [ ] 分布式常见理论和算法总结完善 ### 捐赠支持 diff --git "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" "b/docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" similarity index 100% rename from "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" rename to "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\345\255\227\347\254\246\344\270\262\347\256\227\346\263\225\351\242\230.md" diff --git "a/docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" "b/docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" similarity index 100% rename from "docs/dataStructures-algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" rename to "docs/cs-basics/algorithms/\345\207\240\351\201\223\345\270\270\350\247\201\347\232\204\351\223\276\350\241\250\347\256\227\346\263\225\351\242\230.md" diff --git "a/docs/dataStructures-algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" "b/docs/cs-basics/algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" similarity index 100% rename from "docs/dataStructures-algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" rename to "docs/cs-basics/algorithms/\345\211\221\346\214\207offer\351\203\250\345\210\206\347\274\226\347\250\213\351\242\230.md" diff --git a/docs/dataStructures-algorithms/data-structure/bloom-filter.md b/docs/cs-basics/data-structure/bloom-filter.md similarity index 74% rename from docs/dataStructures-algorithms/data-structure/bloom-filter.md rename to docs/cs-basics/data-structure/bloom-filter.md index bfb7efe7f03..9b5afd6d5c5 100644 --- a/docs/dataStructures-algorithms/data-structure/bloom-filter.md +++ b/docs/cs-basics/data-structure/bloom-filter.md @@ -6,18 +6,18 @@ 2. 布隆过滤器的原理介绍。 3. 布隆过滤器使用场景。 4. 通过 Java 编程手动实现布隆过滤器。 -5. 利用Google开源的Guava中自带的布隆过滤器。 +5. 利用 Google 开源的 Guava 中自带的布隆过滤器。 6. Redis 中的布隆过滤器。 ### 1.什么是布隆过滤器? 首先,我们需要了解布隆过滤器的概念。 -布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的的 List、Map 、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。 +布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于 1970 年提出的。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的的 List、Map 、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。 ![布隆过滤器示意图](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/布隆过滤器-bit数组.png) -位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。 +位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。 总结:**一个名叫 Bloom 的人提出了一种来检索元素是否在给定大集合中的数据结构,这种数据结构是高效且性能很好的,但缺点是具有一定的错误识别率和删除难度。并且,理论情况下,添加到集合中的元素越多,误报的可能性就越大。** @@ -35,11 +35,9 @@ 举个简单的例子: - - ![布隆过滤器hash计算](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/布隆过滤器-hash运算.png) -如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 1(当位数组初始化时,所有位置均为0)。当第二次存储相同字符串时,因为先前的对应位置已设置为 1,所以很容易知道此值已经存在(去重非常方便)。 +如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 1(当位数组初始化时,所有位置均为 0)。当第二次存储相同字符串时,因为先前的对应位置已设置为 1,所以很容易知道此值已经存在(去重非常方便)。 如果我们需要判断某个字符串是否在布隆过滤器中时,只需要对给定字符串再次进行相同的哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。 @@ -49,7 +47,7 @@ ### 3.布隆过滤器使用场景 -1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。 +1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。 2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。 ### 4.通过 Java 编程手动实现布隆过滤器 @@ -206,7 +204,7 @@ true 实际使用如下: -我们创建了一个最多存放 最多 1500个整数的布隆过滤器,并且我们可以容忍误判的概率为百分之(0.01) +我们创建了一个最多存放 最多 1500 个整数的布隆过滤器,并且我们可以容忍误判的概率为百分之(0.01) ```java // 创建布隆过滤器对象 @@ -224,7 +222,7 @@ System.out.println(filter.mightContain(1)); System.out.println(filter.mightContain(2)); ``` -在我们的示例中,当`mightContain()` 方法返回 *true* 时,我们可以99%确定该元素在过滤器中,当过滤器返回 *false* 时,我们可以100%确定该元素不存在于过滤器中。 +在我们的示例中,当`mightContain()` 方法返回 _true_ 时,我们可以 99%确定该元素在过滤器中,当过滤器返回 _false_ 时,我们可以 100%确定该元素不存在于过滤器中。 **Guava 提供的布隆过滤器的实现还是很不错的(想要详细了解的可以看一下它的源码实现),但是它有一个重大的缺陷就是只能单机使用(另外,容量扩展也不容易),而现在互联网一般都是分布式的场景。为了解决这个问题,我们就需要用到 Redis 中的布隆过滤器了。** @@ -234,17 +232,17 @@ System.out.println(filter.mightContain(2)); Redis v4.0 之后有了 Module(模块/插件) 功能,Redis Modules 让 Redis 可以使用外部模块扩展其功能 。布隆过滤器就是其中的 Module。详情可以查看 Redis 官方对 Redis Modules 的介绍 :https://redis.io/modules -另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom。其他还有: +另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom。其他还有: - redis-lua-scaling-bloom-filter(lua 脚本实现):https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter -- pyreBloom(Python中的快速Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom +- pyreBloom(Python 中的快速 Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom - ...... RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、JavaScript 和 PHP。 -#### 6.2 使用Docker安装 +#### 6.2 使用 Docker 安装 -如果我们需要体验 Redis 中的布隆过滤器非常简单,通过 Docker 就可以了!我们直接在 Google 搜索 **docker redis bloomfilter** 然后在排除广告的第一条搜素结果就找到了我们想要的答案(这是我平常解决问题的一种方式,分享一下),具体地址:https://hub.docker.com/r/redislabs/rebloom/ (介绍的很详细 )。 +如果我们需要体验 Redis 中的布隆过滤器非常简单,通过 Docker 就可以了!我们直接在 Google 搜索 **docker redis bloomfilter** 然后在排除广告的第一条搜素结果就找到了我们想要的答案(这是我平常解决问题的一种方式,分享一下),具体地址:https://hub.docker.com/r/redislabs/rebloom/ (介绍的很详细 )。 **具体操作如下:** @@ -252,15 +250,15 @@ RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、Ja ➜ ~ docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest ➜ ~ docker exec -it redis-redisbloom bash root@21396d02c252:/data# redis-cli -127.0.0.1:6379> +127.0.0.1:6379> ``` -#### 6.3常用命令一览 +#### 6.3 常用命令一览 -> 注意: key : 布隆过滤器的名称,item : 添加的元素。 +> 注意: key : 布隆过滤器的名称,item : 添加的元素。 -1. **`BF.ADD `**:将元素添加到布隆过滤器中,如果该过滤器尚不存在,则创建该过滤器。格式:`BF.ADD {key} {item}`。 -2. **`BF.MADD `** : 将一个或多个元素添加到“布隆过滤器”中,并创建一个尚不存在的过滤器。该命令的操作方式`BF.ADD`与之相同,只不过它允许多个输入并返回多个值。格式:`BF.MADD {key} {item} [item ...]` 。 +1. **`BF.ADD`**:将元素添加到布隆过滤器中,如果该过滤器尚不存在,则创建该过滤器。格式:`BF.ADD {key} {item}`。 +2. **`BF.MADD`** : 将一个或多个元素添加到“布隆过滤器”中,并创建一个尚不存在的过滤器。该命令的操作方式`BF.ADD`与之相同,只不过它允许多个输入并返回多个值。格式:`BF.MADD {key} {item} [item ...]` 。 3. **`BF.EXISTS` ** : 确定元素是否在布隆过滤器中存在。格式:`BF.EXISTS {key} {item}`。 4. **`BF.MEXISTS`** : 确定一个或者多个元素是否在布隆过滤器中存在格式:`BF.MEXISTS {key} {item} [item ...]`。 @@ -268,19 +266,19 @@ root@21396d02c252:/data# redis-cli 这个命令的格式如下: -`BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion] `。 +`BF.RESERVE {key} {error_rate} {capacity} [EXPANSION expansion]`。 下面简单介绍一下每个参数的具体含义: 1. key:布隆过滤器的名称 -2. error_rate :误报的期望概率。这应该是介于0到1之间的十进制值。例如,对于期望的误报率0.1%(1000中为1),error_rate应该设置为0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的CPU使用率越高。 -3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。 +2. error_rate :误报的期望概率。这应该是介于 0 到 1 之间的十进制值。例如,对于期望的误报率 0.1%(1000 中为 1),error_rate 应该设置为 0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的 CPU 使用率越高。 +3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。 可选参数: -- expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。 +- expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以`expansion`。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。 -#### 6.4实际使用 +#### 6.4 实际使用 ```shell 127.0.0.1:6379> BF.ADD myFilter java @@ -294,4 +292,3 @@ root@21396d02c252:/data# redis-cli 127.0.0.1:6379> BF.EXISTS myFilter github (integer) 0 ``` - diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\233\276.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\233\276.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\233\276.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\233\276.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\345\271\277\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\227\240\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\347\237\251\351\230\265\345\255\230\345\202\250\347\232\204\345\211\257\346\234\254.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\234\211\345\220\221\345\233\276\347\232\204\351\202\273\346\216\245\350\241\250\345\255\230\345\202\250.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2421.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2422.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2423.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2424.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2425.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\2426.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.drawio" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" "b/docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" rename to "docs/cs-basics/data-structure/pictures/\345\233\276/\346\267\261\345\272\246\344\274\230\345\205\210\346\220\234\347\264\242\345\233\276\347\244\272.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2401.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2402.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2403.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2404.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2405.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\210\240\351\231\244\345\240\206\351\241\266\345\205\203\347\264\2406.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2401.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2402.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206-\346\217\222\345\205\245\345\205\203\347\264\2403.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2061.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2061.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2061.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2061.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2062.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2062.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\2062.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\2062.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2171.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2172.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2173.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2174.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2175.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\346\216\222\345\272\2176.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\240\206\347\232\204\345\255\230\345\202\250.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2061.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2062.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2063.png" diff --git "a/docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" "b/docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" similarity index 100% rename from "docs/dataStructures-algorithms/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" rename to "docs/cs-basics/data-structure/pictures/\345\240\206/\345\273\272\345\240\2064.png" diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio" new file mode 100644 index 00000000000..f8fe81d2c06 --- /dev/null +++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.drawio" @@ -0,0 +1 @@ +7Vtbk6I4FP41eZwukgBJHr1g727tVk1VV+30PNKSVmbQuIit7q/fBAISBLVbFHfa8sHkJORyzpcv5xwR4MFs8xj7i+lfIuARQFawAXgIEILQcuWXkmwzCWMkE0ziMNCddoKn8F+uhZaWrsKAL42OiRBREi5M4VjM53ycGDI/jsXa7PYqInPWhT/he4KnsR/tS7+FQTLNpBSRnfw3Hk6m+czQZVnLzM87650sp34g1iUR9gAexEIkWWm2GfBIKS/XS/bcqKG1WFjM58kpD6yenT8ev/39O3VCf/C2ZpuF7X/Ro7z50UpvGCA3kuP1X9SSk63Wg/vPSq2z/yrmyZdlaqWe7ICcxWbXKEsT9d3Lx5CLecmFWgnFiEiuThpRVvrraZjwp4U/Vi1riSMpmyazSNagLPrLRWbZ13DDA7WIMIoGIhJxOhB+feXueCzlyyQWP3mpJSDsxbKKyd94nPBNo/pgYRSJZi5mPIm3sot+gGBtRw1kzHR9XYKFFk1LiMhlvgbipBh5ZytZ0OZ6h+lQjemqKp4HPXUGZG0u5txUq9x3vH0uV76XK0O1b6uobXUtm4MHe6emoke5DrGKx/zABrA+zn484ckxjO7bpaR3p0bvuSzmkZ+Eb+Zy64yhZ/gqQrmRndktYpidWBV7ZtvUT5WPX3Ug5jwgaiMCkU1sN1+JHtYm1GzF5iyZkvZmSYFT6OTjWMKNNLBc+POPM0GJTDLBoJ4aClk23a/BGJSajGF3zRj2tazc/0RWdq0bs7JzLSsPP5GVHWRa2SEdW9m9lpUfP5GVmXtjVibn+nibMHkulb/nPp0s7xw8Vcn9u8IrLCpX9grt/4NX6FaAQuAHvUKKqIk4hq7q+NFzAVYbRFhH4JLD0irBEh6EZQcAc7oEGKneN+yjYYdDD4UdrNOwg52JvhZR4Z6ICtwlKiiCDy7GDrapdEgQNI3pUPjAIGO27AZtNw9c301J2D2AGIdada1XAkxOs5d3e7xP5Pa49MbcHliXljzX7zl8wdT7Pccusi78HqvelldyfMw8FWQmcCB8INAhiBIHOZhWhj/5zrJqh8nvLFq7hGsxEGpkIEU0LTKQfYSBsukaGEiSQWIeCZNB9JEp040W+VE4mcvqWCKYS3lfUUs49qOebpiFQRA1cVssVvNAMdmwLW5ilfSKtc9Ndg3e0cW4qTlX2jIA0B0AilOcyuXUOQCa06gtA8C9AyD1R28NAM0Z1pYBAO8ASC/8CgBo1wBw971R6QI+6arWoqkHESdTMRFzP/pTiIU2yA+eJFv9zoO/SkRDbsV6cDpKxuVvXHwwGXeys3meOeqypBcJCkefKCik1q0Fha3lKt+V2n5/Cr3N80dOPICdpqWgZQZsxIwKXYjrWt8bFbKDmUwJzy7zUnWZzIu4BM7dJZAthNyYS5APfHkAkDsAFBlUg4LOAdD8JmXLAMB3AKhLxb41ADQnBs/zQod9rzcalF/DOOhm/jIWJpXf2N3OLYz3/c1LhH35j+NZ1HdtlzPH8VGXM+vYVdCHarJwngP6Huh5wLOBjNV6EHguYBZgA+AhQNOCycnjInbanToZXzGG8f5BfAyT6epFjUk9wCjwGKAEMDkLVZOq6RxAKWCoiY31KoYFp8en0AK0a+8FORnrA+apQs8GdNjKJr8OR0dXL/crNSA9EbXfEWCuXotUvlIFAT1c0glRBUZSWwxAv5d2HqUFojrkx/rmOCzyX3jU98c/J6m8OrlUjT7D0Nb1UijeTz8theLQZEIb7zNhQXtnUqGs7v6SkoVHuz/2YO8/ \ No newline at end of file diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\206.png" new file mode 100644 index 0000000000000000000000000000000000000000..3ad5782c8bde94ea9d99f36987b69e2578f20024 GIT binary patch literal 35285 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 Ja$)_i{~rKnb#4Fv literal 0 HcmV?d00001 diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio" new file mode 100644 index 00000000000..31e3097a914 --- /dev/null +++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.drawio" @@ -0,0 +1 @@ +5ZhNc5swEIZ/jY/uYLDBHGPsuIdmpmMfmhxlkEGtYKkQBvLrK1niq46bJm0Zpj6hfSWtpH12NSMmlheXW4bS6AECTCemEZQTaz0xzdnMsMVHKpVSXNdRQshIoAe1wp48Yy0aWs1JgLPeQA5AOUn7og9Jgn3e0xBjUPSHHYH2V01RiC+EvY/opfqFBDxS6tJ0Wv0jJmFUrzyzXdUTo3qwPkkWoQCKjmRtJpbHALhqxaWHqQxeHRc17/5Kb7MxhhP+OxN22UPg7CLH2z06MV1Pt0bxPNVeTojm+sAT06bC3+ogt8wrHQf7ey73uTpCwqfZmdKdGGAu0rLtFK1Qfu9qH2Izh1rUQWg8mmJ3AqIwVkVEON6nyJc9hcgjoUU8psKaiSbKUkX2SEocyE0QSj2gwM6OrOMR274v9Iwz+IY7PYHjHgyjWfyEGcfl1fDNGigimzHEmLNKDNET7DojdSLPa7vopIWWok5G1BrSiRg2nltWoqFxvQGdeRVdlqLk/fQ6CaAE72WcjaaW+z8oO+7IKFtDUV7dEOW5NTLK86Eor2+IsjUfGeXFUJS3N0R56bjjomwPRXlzQ5QX5shq2bmMaCAeDtpMIJGhZZAngQzaWoYBGI8ghATRTwCpDu9XzHmlnz0o59APvogOqx7l/A+L2nzq9q1L7VxZlbbey0ie4deExJEhZz5+/U3BEQsxf23cJXGGKeLk1N/HX+e3HKpK72+oSh1jZFXqDlOlJeGdIhXWU12Vot2WqDT+fYX+QUXpqZ+BCI/ty/enu7e5i2sX6kbQs7p/IN7qSF0ZF47O6JvzvJQNwmx/pKjh7e8oa/MD \ No newline at end of file diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\344\270\255\345\272\217\351\201\215\345\216\2062.png" new file mode 100644 index 0000000000000000000000000000000000000000..fe6956b9d09c3503aaa88c0d3ed833d0f9b9d1a6 GIT binary patch literal 11447 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 b=Il4%yripmCIPsRd`2Cnqg<+J^W?t(mQb_Y literal 0 HcmV?d00001 diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio" new file mode 100644 index 00000000000..b92e5c29cc9 --- /dev/null +++ "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.drawio" @@ -0,0 +1 @@ +7Vtbk6I4FP41eZwuIDfyKIq9D7tVU9u1tTOPKGllGo2L2Or8+k0kIEFQ2xvOtOWDyUnI5ZwvJ985IoDdyeo5CWbjv0TIY+BY4QrAHnAc27aI/FKSdSZhjGaCURKFutNW8BL95FpoaekiCvnc6JgKEafRzBQOxXTKh6khC5JELM1uryI2Z50FI74jeBkG8a703yhMx5nUdehW/gePRuN8ZpuwrGUS5J31TubjIBTLkgj6AHYTIdKsNFl1eayUl+sle67f0FosLOHT9JgHEuvvH2+rZPbTI6O56/T+WTrPX/Qo70G80BsGDonleN5ALTldaz2Q/xZqnd6rmKZf5hsrdWQHB89W20ZZGqnvTj6GXMwgF2olFCM6cnXSiLLiLcdRyl9mwVC1LCWOpGycTmJZs2UxmM8yy75GKx6qRURx3BWxSDYDwddXToZDKZ+niXjjpZaQsoFlFZO/8yTlq0b12YVRJJq5mPA0Wcsu+gGCtB01kCHW9WUJFlo0LiEilwUaiKNi5K2tZEGb6wOmc2pMV1XxNOyoMyBrUzHlplrlvpP1t3Lle7nSU/u2itpa17I5eLhzaip6lOsQi2TI92wA6uMcJCOeHsLorl1Kesc1es9lCY+DNHo3l1tnDD3DVxHJjWzNblPD7IRU7JltUz9VPn6VgaiFnxwXOdR2EEUkX4keFkHXbIXmLJmSdmbZAKfQyelYgo1uYD4Lpqd7gpIzyQTdetdQyLLpfg+PQZnpMVDbHgPdysreJ7Iytu/MyvhWVu59IisjaFoZw5atTG5l5edPZGWX3pmV6bkcbxWl30rl7zmnk+UtwVOVnN8VrLCo3JgVol+BFeIKUAg9lRVC10Qcdm5K/NxzAVYbRFgH4JLD0irB0t4LyxYAhtsEGKneN/hEgBHi7gs7cKthBzsTfRdEBTkSFbBNVFBoPxEIMUQulhe4bRoTI/uJ2YwhV7YgYtETXRIiexCDkVXXeiPA5Fz7+rTH/0S0B7M7oz12XVryXN6z/4Kp5z2HLrI2eI9Vb8sbER/XuDBsZl4n1H6iNqaSSGOJIrcy/NF3ll07TD4Jql3CrTyQ0+iBlKO5oAeyD3igbLoGDySdQWoeCdOD6CNTdjdaFMTRaCqrQ4lgLuWeci3RMIg7umEShWHc5NsSsZiGypP1LpV2typpd7Lrm1AN3p2r+abmXOmFAeA8AKCMS0wAoNYB0JxGvTAA8AMAGz56bwBozrBeGADwAQDl8qv0FLUNALLLRiUFfNFVrUVTDyJJx2IkpkH8pxAzbZAfPE3X+p2HYJGKhtyK9YRbSsblb1ycmIw7mmyeZ466LOlVgsL+JwoKqX1vQeHFcpUfSm1/PIV+yfNHjzyAraalmBmvUTMoxBTWtX40KHT3JjIlOttMS9UlMq/CCMiDEcgW4t4ZI8gHvj4A6AMAyhmgewNA84uUFwYAegAAlH4PuxsANOcFzyOhHa/nd/vltzD2sszfxsKk+hN76xaGu3TzGlFf/tt4FvTdmnHmOD7IOLOObcV8Tk0SzsfA80HHBz4CMlTr2MAngFmAdYHvAHdTMH3ysAidtqdOhleMQbh7EJ+jdLwYqDFdHzAX+Ay4FDA5i6smVdNh4LqAOU3eWK+iV/j05Bi3YKPae0FOxjzAfFXoIOD2LrLJr73+wdXL/UoNSCai9tsHjOi1SOUrVVDQgSWdUFVgdGOLLvA6m879TYGqDjmVuzsfFgcDHnvB8G20kVcnl6rRZ9hGul6KxL3N50KReOVdkCIfVvKEhds70xXK6vYfKVl4tP1fD/T/Bw== \ No newline at end of file diff --git "a/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png" "b/docs/cs-basics/data-structure/pictures/\346\240\221/\345\205\210\345\272\217\351\201\215\345\216\206.png" new file mode 100644 index 0000000000000000000000000000000000000000..5c80cedf7d6561c8aa8c55d7762d4ea5edd17b02 GIT binary patch literal 35364 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