From d34ed95271c26b32daf70516f5c68855bc505c04 Mon Sep 17 00:00:00 2001
From: msJavaCoder <271457837@qq.com>
Date: Sun, 24 Jan 2021 13:19:04 +0800
Subject: [PATCH 001/138] =?UTF-8?q?feat:=E5=8D=95=E4=BE=8B=E6=A8=A1?=
=?UTF-8?q?=E5=BC=8F=E6=80=BB=E7=BB=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
_sidebar.md | 7 +-
...25\344\276\213\346\250\241\345\274\217.md" | 249 ++++++++++++++++++
index.html | 2 +-
.../HungryStaticSingleton.java" | 35 +++
.../LazyDoubleCheckSingleton.java" | 38 +++
.../LazySimpleSingleton.java" | 31 +++
.../LazyStaticInnerClassSingleton.java" | 29 ++
.../Singleton.java" | 33 +++
8 files changed, 420 insertions(+), 4 deletions(-)
create mode 100644 "docs/\350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md"
create mode 100644 "src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/HungryStaticSingleton.java"
create mode 100644 "src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyDoubleCheckSingleton.java"
create mode 100644 "src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazySimpleSingleton.java"
create mode 100644 "src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyStaticInnerClassSingleton.java"
create mode 100644 "src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/Singleton.java"
diff --git a/_sidebar.md b/_sidebar.md
index 1d9a1dd..9209fd3 100644
--- a/_sidebar.md
+++ b/_sidebar.md
@@ -74,12 +74,13 @@
* SpringBoot专栏
* [SpringBoot常用注解](docs/SpringBoot/SpringBoot的常用注解.md)
-
-
-* SpringBoot常用技术整合
* [SpringBoot-MyBatisPlus](docs/SpringBoot/基于SpringBoot集成Mybatis-Plus实现代码生成器.md)
* ...
+* 设计模式
+ * [单例模式](docs/设计模式/单例模式.md)
+ * ...
+
* 面试题
* [Java核心面试题汇总](docs/面试题/Java核心面试题汇总.md)
* [Spring核心面试题汇总](docs/面试题/Spring面试题汇总.md)
diff --git "a/docs/\350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md" "b/docs/\350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md"
new file mode 100644
index 0000000..6196b2c
--- /dev/null
+++ "b/docs/\350\256\276\350\256\241\346\250\241\345\274\217/\345\215\225\344\276\213\346\250\241\345\274\217.md"
@@ -0,0 +1,249 @@
+# 单例模式
+
+## 1. 单例模式的定义
+
+ **单例模式指的是一个类中在任何情况下都绝对只有一个实例,并且提供一个全局访问点。**
+
+## 2. 单例模式的应用场景
+
+> 单例模式的应用非常广泛,如数据库中的连接池、J2EE中的ServletContext和ServletContextConfig、Spring框架中的ApplicationContext等等。然而在Java中,单例模式还可以保证一个JVM中只存在一个唯一的实例。
+
+单例模式的应用场景主要有以下几个方面:
+
+- 当需要频繁创建一些类的时候,使用单例可以降低系统的内存压力,减少GC(垃圾回收) ;
+- 当某些类创建实例时候需要占用的资源较多,或者实例化过程耗时比较长,且经常使用的情况;
+- 当存在频繁访问数据库或者文件的对象;
+- 当对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,是不允许存在多个实例的,否则玩完;
+
+## 3. 单例模式的优缺点
+
+### 3.1 单例模式的优点
+
+- **单例模式可以保证内存中只有一个实例对象,从而会减少内存的开销;**
+- **单例模式可以避免对资源的多重占用;**
+- **单例模式设置全局访问点,可以起到优化和共享资源的访问的作用;**
+
+### 3.2 单例模式的缺点
+
+- **扩展难**, 因为单例模式通常是没有接口的啊,如果想要扩展,那么你唯一途径就是修改之前的代码,所以说单例模式违背了开闭原则;
+- **调试难**,因为在并发测试中,单例模式是不利于代码的调试的,单例中的代码没有执行完,也不能模拟生成一个新对象;
+- **违背单一职责原则**,因为单例模式的业务代码通常写在一个类中,如果功能设计不合理,就很容易违背单一职责原则;
+
+## 4. 单例模式的实现方式及其优缺点
+
+### 4.1 单例模式的饿汉式实现
+
+#### 4.1.1 饿汉式标准写法
+
+ **Singleton类称为单例类,通过内部初始化一次 , 隐藏构造方法, 并提供一个全局访问点的方式实现。**
+
+```java
+/**
+ * msJava
+ *
+ * @Description 单例模式的通用写法
+ * @Date 2021-01-23
+ */
+public class Singleton {
+ /**
+ * 内部初始化一次
+ */
+ private static final Singleton instance = new Singleton();
+
+ /**
+ * 隐藏构造方法
+ */
+ private Singleton() {
+ }
+
+ /**
+ * 提供一个全局访问点
+ *
+ * @return Singleton
+ */
+ public static Singleton getInstance() {
+ return instance;
+ }
+
+}
+
+```
+
+ **以上饿汉式单例写法在类的初始化的时候就会进行初始化操作,并且创建对象,绝对的线程安全,因为此时线程还没有出现就已经实例化了,故不会存在访问安全的问题。**
+
+#### 4.1.2 饿汉式静态块机制写法
+
+ **饿汉式还有一种实现,那就是静态块机制,如下代码所示:**
+
+```java
+/**
+ * msJava
+ *
+ * @Description 单例模式 饿汉式静态机制 实现
+ * @Date 2021-01-23
+ */
+public class HungryStaticSingleton {
+
+ private static final HungryStaticSingleton hungrySingleton;
+ //静态代码块 类加载的时候就初始化
+ static {
+ hungrySingleton=new HungryStaticSingleton();
+ }
+ /**
+ * 私有化构造函数
+ */
+ private HungryStaticSingleton(){}
+
+ /**
+ * 提供一个全局访问点
+ * @return
+ */
+ public static HungryStaticSingleton getInstance() {
+ return hungrySingleton;
+ }
+}
+```
+
+ **我们分析一下这种是写法 ,可以明显的看到所以对象是类在加载的时候就进行实例化了,那么这样一来,会导致单例对象的数量不确定,从而会导致系统初始化的时候就造成大量内存浪费,况且你用不用还不一定,还一直占着空间,俗称“占着茅坑不拉屎”。**
+
+### 4.2 单例模式的懒汉式实现
+
+ **为了解决饿汉式单例写法可能带来的内存浪费问题,这里分析一下懒汉式单例的写法。如下代码所示:**
+
+```java
+/**
+ * msJava
+ *
+ * @Description 单例模式 懒汉式单例实现
+ * @Date 2021-01-23
+ */
+public class LazySimpleSingleton {
+
+ private static LazySimpleSingleton lazySingleton = null;
+
+ /**
+ * 私有化构造函数
+ */
+ private LazySimpleSingleton() {
+
+ }
+ /**
+ * 提供一个全局访问点
+ *
+ * @return
+ */
+ public static LazySimpleSingleton getInstance() {
+ if (lazySingleton == null) {
+ lazySingleton = new LazySimpleSingleton();
+ }
+ return lazySingleton;
+ }
+}
+
+```
+
+ **这样实现的好处就是只有对象被使用的时候才会进行初始化,不会存在内存浪费的问题,但是它会在多线程环境下,存在线程安全问题。我们可以利用synchronized关键字将全局访问点方法变成一个同步方法,这样就可以解决线程安全的问题,代码如下所示:**
+
+```java
+/**
+ * msJava
+ *
+ * @Description 单例模式 懒汉式单例实现 synchronized修饰
+ * @Date 2021-01-23
+ */
+public class LazySimpleSingleton {
+ private static LazySimpleSingleton lazySingleton = null;
+ /**
+ * 私有化构造函数
+ */
+ private LazySimpleSingleton() {}
+ /**
+ * 提供一个全局访问点
+ *
+ * @return
+ */
+ public synchronized static LazySimpleSingleton getInstance() {
+ if (lazySingleton == null) {
+ lazySingleton = new LazySimpleSingleton();
+ }
+ return lazySingleton;
+ }
+}
+```
+
+ **但是,这样虽然解决了线程安全的问题,可是如果在线程数量剧增的情况下,用synchronized加锁,则会导致大批线程阻塞,从而骤减系统性能。**
+
+### 4.3 单例模式的双重检测实现
+
+ 在上述代码上进一步优化,代码如下所示:
+
+```java
+
+/**
+ * msJava
+ *
+ * @Description 单例模式 懒汉式-双重检测单例实现
+ * @Date 2021-01-23
+ */
+public class LazyDoubleCheckSingleton {
+ // volatile 关键字修饰
+ private volatile static LazyDoubleCheckSingleton lazySingleton ;
+ /**
+ * 私有化构造函数
+ */
+ private LazyDoubleCheckSingleton() {}
+ /**
+ * 提供一个全局访问点
+ *
+ * @return
+ */
+ public static LazyDoubleCheckSingleton getInstance() {
+ // 这里先判断一下是否阻塞
+ if (lazySingleton == null) {
+ synchronized (LazyDoubleCheckSingleton.class){
+ // 判断是否需要重新创建实例
+ if (lazySingleton == null) {
+ lazySingleton = new LazyDoubleCheckSingleton();
+ }
+ }
+ }
+ return lazySingleton;
+ }
+}
+```
+
+ **当第一个线程调用getInstance()方法时,第二个线程也可以调用,但是第一个线程执行synchronized时候,第二个线程就会发现阻塞,但是此时的阻塞是getInstance()内部的阻塞。**
+
+#### 4.4 单例模式的静态内部类实现
+
+ **虽然双重检测锁的单例模式解决了线程安全和性能问题,但是毕竟涉及加锁的操作,多多少少就会到了性能的影响,下面我们分享一下更加优雅的单例模式实现,如下代码所示:**
+
+```java
+/**
+ * msJava
+ *
+ * @Description 单例模式 静态内部类单例实现
+ * @Date 2021-01-23
+ */
+public class LazyStaticInnerClassSingleton {
+ // 在构造方法里面抛出异常真的合适?
+ private LazyStaticInnerClassSingleton(){
+ if(LazyHolder.INSTANCE != null){
+ throw new RuntimeException("不允许创建多个实例");
+ }
+ }
+ // static 保证这个方法不会被重写 覆盖
+ private static LazyStaticInnerClassSingleton getInstance(){
+ return LazyHolder.INSTANCE;
+ }
+ // Java 默认不会加载内部类
+ private static class LazyHolder{
+ private static final LazyStaticInnerClassSingleton INSTANCE=new LazyStaticInnerClassSingleton();
+ }
+}
+
+```
+
+## 5. 总结
+
+ 单例模式面试几乎必备!
\ No newline at end of file
diff --git a/index.html b/index.html
index 60b0f9c..88da6ad 100644
--- a/index.html
+++ b/index.html
@@ -21,7 +21,7 @@
window.$docsify = {
name: '🔥码上Java',
repo: 'https://github.com/msJavaCoder/msJava',
- maxLevel: 5,//最大支持渲染的标题层级
+ maxLevel: 5,//最大支持渲染的标题层级+Z z--
subMaxLevel: 0,
homepage: "README.md",
coverpage: true,
diff --git "a/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/HungryStaticSingleton.java" "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/HungryStaticSingleton.java"
new file mode 100644
index 0000000..e23dc09
--- /dev/null
+++ "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/HungryStaticSingleton.java"
@@ -0,0 +1,35 @@
+package com.imood.msjava.设计模式;
+
+/**
+ * msJava
+ *
+ * @Description 单例模式 饿汉式静态机制 实现
+ * @Date 2021-01-23
+ */
+public class HungryStaticSingleton {
+
+
+ private static final HungryStaticSingleton hungrySingleton;
+
+ //静态代码块 类加载的时候就初始化
+ static {
+ hungrySingleton=new HungryStaticSingleton();
+ }
+
+ /**
+ * 私有化构造函数
+ */
+ private HungryStaticSingleton(){
+
+ }
+
+ /**
+ * 提供一个全局访问点
+ * @return
+ */
+ public static HungryStaticSingleton getInstance() {
+ return hungrySingleton;
+ }
+
+
+}
diff --git "a/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyDoubleCheckSingleton.java" "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyDoubleCheckSingleton.java"
new file mode 100644
index 0000000..9587426
--- /dev/null
+++ "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyDoubleCheckSingleton.java"
@@ -0,0 +1,38 @@
+package com.imood.msjava.设计模式;
+
+/**
+ * msJava
+ *
+ * @Description 单例模式 懒汉式单例实现
+ * @Date 2021-01-23
+ */
+public class LazyDoubleCheckSingleton {
+
+ // volatile 关键字修饰
+ private volatile static LazyDoubleCheckSingleton lazySingleton ;
+
+ /**
+ * 私有化构造函数
+ */
+ private LazyDoubleCheckSingleton() {
+
+ }
+
+ /**
+ * 提供一个全局访问点
+ *
+ * @return
+ */
+ public static LazyDoubleCheckSingleton getInstance() {
+ // 这里先判断一下是否阻塞
+ if (lazySingleton == null) {
+ synchronized (LazyDoubleCheckSingleton.class){
+ // 判断是否需要重新创建实例
+ if (lazySingleton == null) {
+ lazySingleton = new LazyDoubleCheckSingleton();
+ }
+ }
+ }
+ return lazySingleton;
+ }
+}
diff --git "a/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazySimpleSingleton.java" "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazySimpleSingleton.java"
new file mode 100644
index 0000000..d977069
--- /dev/null
+++ "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazySimpleSingleton.java"
@@ -0,0 +1,31 @@
+package com.imood.msjava.设计模式;
+
+/**
+ * msJava
+ *
+ * @Description 单例模式 懒汉式单例实现
+ * @Date 2021-01-23
+ */
+public class LazySimpleSingleton {
+
+ private static LazySimpleSingleton lazySingleton = null;
+
+ /**
+ * 私有化构造函数
+ */
+ private LazySimpleSingleton() {
+
+ }
+
+ /**
+ * 提供一个全局访问点
+ *
+ * @return
+ */
+ public static LazySimpleSingleton getInstance() {
+ if (lazySingleton == null) {
+ lazySingleton = new LazySimpleSingleton();
+ }
+ return lazySingleton;
+ }
+}
diff --git "a/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyStaticInnerClassSingleton.java" "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyStaticInnerClassSingleton.java"
new file mode 100644
index 0000000..6d631e2
--- /dev/null
+++ "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/LazyStaticInnerClassSingleton.java"
@@ -0,0 +1,29 @@
+package com.imood.msjava.设计模式;
+
+/**
+ * msJava
+ *
+ * @Description 单例模式 静态内部类单例实现
+ * @Date 2021-01-23
+ */
+public class LazyStaticInnerClassSingleton {
+
+ // 在构造方法里面抛出异常真的合适?
+ //
+ private LazyStaticInnerClassSingleton(){
+ if(LazyHolder.INSTANCE != null){
+ throw new RuntimeException("不允许创建多个实例");
+ }
+ }
+
+ // static 保证这个方法不会被重写 覆盖
+ private static LazyStaticInnerClassSingleton getInstance(){
+ return LazyHolder.INSTANCE;
+ }
+
+
+ // Java 默认不会加载内部类
+ private static class LazyHolder{
+ private static final LazyStaticInnerClassSingleton INSTANCE=new LazyStaticInnerClassSingleton();
+ }
+}
diff --git "a/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/Singleton.java" "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/Singleton.java"
new file mode 100644
index 0000000..aad21f7
--- /dev/null
+++ "b/src/com/imood/msjava/\350\256\276\350\256\241\346\250\241\345\274\217/Singleton.java"
@@ -0,0 +1,33 @@
+package com.imood.msjava.设计模式;
+
+/**
+ * msJava
+ *
+ * @Description 单例模式的通用写法
+ * @Date 2021-01-23
+ */
+public class Singleton {
+
+ /**
+ * 内部初始化一次
+ */
+ private static final Singleton instance = new Singleton();
+
+
+ /**
+ * 隐藏构造方法
+ */
+ private Singleton() {
+ }
+
+ /**
+ * 提供一个全局访问点
+ *
+ * @return Singleton
+ */
+ public static Singleton getInstance() {
+ return instance;
+ }
+
+
+}
From 526b6383b0203d604f2be0412aea227cd460442f Mon Sep 17 00:00:00 2001
From: msJavaCoder <271457837@qq.com>
Date: Tue, 26 Jan 2021 21:14:53 +0800
Subject: [PATCH 002/138] =?UTF-8?q?fix=20=EF=BC=9A=20=E7=9B=AE=E5=BD=95?=
=?UTF-8?q?=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
_sidebar.md | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/_sidebar.md b/_sidebar.md
index 9209fd3..aecd90f 100644
--- a/_sidebar.md
+++ b/_sidebar.md
@@ -1,9 +1,3 @@
-* 网络
- * [理解网络协议分层](docs/计算机网络/网络协议分层.md)
- * [理解TCP和UDP](docs/计算机网络/理解TCP和UDP.md)
- * [理解HTTP和HTTPS](docs/计算机网络/理解HTTP与HTTPS.md)
- * ...
-
* Java核心基础
* [理解基本数据类型与包装类](docs/Java万岁/Java-基础不牢地动山摇/理解基本数据类型与包装类.md)
* [理解类与Object](docs/Java万岁/Java-基础不牢地动山摇/理解类与Object.md)
@@ -18,7 +12,7 @@
* [理解克隆与序列化应用](docs/Java万岁/Java-基础不牢地动山摇/理解克隆与序列化应用.md)
* ...
-* 集合
+* Java集合
* [理解集合Collection](docs/Java万岁/Java-基础不牢地动山摇/理解集合Collection.md)
* [理解集合Map](docs/Java万岁/Java-基础不牢地动山摇/理解集合Map.md)
* [理解HashMap底层实现原理](docs/Java万岁/Java-基础不牢地动山摇/理解HashMap底层实现原理.md)
@@ -52,7 +46,7 @@
* [理解线程安全synchronized与ReentrantLock](docs/并发编程/理解线程安全synchronized与ReentrantLock.md)
* ...
-* JVM
+* JVM虚拟机
* [垃圾回收器](docs/JVM/垃圾回收器.md)
* [垃圾回收算法](docs/JVM/垃圾回收算法.md)
* [类加载机制](docs/JVM/类加载机制.md)
@@ -60,7 +54,7 @@
* [JVM确认可回收对象的方式](docs/JVM/JVM确认可回收对象的方式.md)
* ...
-* 数据库
+* MySQL数据库
* [理解MySQL基础概念](docs/MySQL/MySQL基础概念.md)
* [教你如何使用索引](docs/MySQL/如何使用索引.md)
* [什么情况下索引会失效](docs/MySQL/什么情况下索引失效.md)
@@ -72,16 +66,26 @@
* [如何使用EXPLAIN查看执行计划](docs/MySQL/如何使用EXPLAIN查看执行计划.md)
* ...
-* SpringBoot专栏
+* SpringBoot
* [SpringBoot常用注解](docs/SpringBoot/SpringBoot的常用注解.md)
* [SpringBoot-MyBatisPlus](docs/SpringBoot/基于SpringBoot集成Mybatis-Plus实现代码生成器.md)
* ...
+* 算法与数据结构
+ * [常用算法](docs/算法/常用算法.md)
+ * ···
+
+* 网络
+ * [理解网络协议分层](docs/计算机网络/网络协议分层.md)
+ * [理解TCP和UDP](docs/计算机网络/理解TCP和UDP.md)
+ * [理解HTTP和HTTPS](docs/计算机网络/理解HTTP与HTTPS.md)
+ * ...
+
* 设计模式
* [单例模式](docs/设计模式/单例模式.md)
* ...
-* 面试题
+* 面试题专栏
* [Java核心面试题汇总](docs/面试题/Java核心面试题汇总.md)
* [Spring核心面试题汇总](docs/面试题/Spring面试题汇总.md)
* [SpringBoot核心面试题汇总](docs/面试题/SpringBoot面试题汇总.md)
From 7d4940a07125067072e45b13b35833067ed08401 Mon Sep 17 00:00:00 2001
From: msJavaCoder <271457837@qq.com>
Date: Wed, 27 Jan 2021 15:41:28 +0800
Subject: [PATCH 003/138] =?UTF-8?q?index.html=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
index.html | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/index.html b/index.html
index 88da6ad..d2bf2be 100644
--- a/index.html
+++ b/index.html
@@ -22,17 +22,17 @@
name: '🔥码上Java',
repo: 'https://github.com/msJavaCoder/msJava',
maxLevel: 5,//最大支持渲染的标题层级+Z z--
- subMaxLevel: 0,
+ subMaxLevel: 0, // 最大支持渲染的子标题层级
homepage: "README.md",
- coverpage: true,
- loadSidebar: true,
+ coverpage: true, //开启封面
+ loadSidebar: true, //开启侧边栏
auto2top: true,//切换页面后是否自动跳转到页面顶部
search: {
//maxAge: 86400000, // 过期时间,单位毫秒,默认一天
paths: 'auto',
placeholder: ' 🔍 Type to search',
noData: '😞 No Results!',
- depth: 3,
+ depth: 3, // 搜索标题的最大程级, 1 - 6
},
pagination: {
previousText: '上一章',
@@ -46,6 +46,12 @@
if (typeof navigator.serviceWorker !== 'undefined') {
navigator.serviceWorker.register('sw.js')
}
+ window.$docsify = {
+ loadSidebar: true,
+ alias: {
+ '/.*/_sidebar.md': '/_sidebar.md'
+ }
+ }
@@ -60,5 +66,7 @@
+
+