设计模式3——单例模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaojie_570/article/details/87475814

这个模式一年前学完的,今天看看博客竟然没有总结!!!单例模式应该是最早接触的模式了吧!

单例模式分为饿汉式懒汉式

1. 饿汉式(静态常量)

在这里插入图片描述

优点:使用静态常量,因此在类加载的时候创建了,所以是线程安全的。
缺点:因为在类加载的时候就创建了,所以如果程序中从来没有使用过该类的实例,那么就会出现内存浪费。

2. 饿汉式(静态块)

在这里插入图片描述

优点:使用静态常量,因此在类加载的时候创建了,所以是线程安全的。
缺点:因为在类加载的时候就创建了,所以如果程序中从来没有使用过该类的实例,那么就会出现内存浪费。

3. 懒汉式(线程不安全)

在这里插入图片描述

懒汉式:在需要的时候再创建,而不是之前在类加载的时候就在JVM中加载好了。

  • 优点:不会造成内存浪费
  • 缺点:线程不安全-》假设现在两个线程同时执行到了【第13行】,这两个线程同时认为该类中没有INSTANCE实例,就会同时创建INSTANCE实例,导致线程不安全。

4. 懒汉式(线程安全,效率低)

在这里插入图片描述

我们可以看到在【第12行】加了synchronized关键字,我们知道虽然synchronized关键字在JDK1.8中有优化,但是给这一整个方法加锁怎么样说这个锁都太粗了吧。。。

5. 懒汉式(线程不安全,同步代码块)

在这里插入图片描述

为了解决第四种情况的效率低的问题,我们将 synchronized 关键字改在了方法体里面,这次是给类加同步,但是这样会导致线程不安全。为什么呢?
我们还假设 现在有两个线程(A和B)同时到达了【第13行】,这两个线程都得到了 INSTANCE == null。所以又同时到达了【第14行】,假设线程A很幸运抢过了线程B,它得到了锁,那么它吭哧吭哧执行,知道执行到【第16行】之后,将锁释放了,这个时候线程B获取到了锁,那么它会从它卡住的位置继续执行下去,好了!他从哪里卡主的呢?是从【第14行】吧,所以,他继续执行到【第15行】,糟了,又创建了INSTANCE实例。所以就又变成线程不安全的了。

6. 懒汉式(双重检查)

在这里插入图片描述

OK ,这回在 进入同步块之后,又来了一个是否为空的检查,这次就不会出现情况五的问题了,完美解决。效率又高,线程又安全。

7. 静态内部类

在这里插入图片描述

这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。

参考并感谢

https://www.cnblogs.com/zhaoyan001/p/6365064.html

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/87475814