设计模式--单例模式

1. 单例模式介绍

什么是单例模式

单例模式是为了保证一个类只有一个实例,作为唯一的入口。

为什么要使用单例模式

因为有的类只需要一个实例即可,不用过多的创建实例,从而节省内存开销,减少不必要的浪费

单例模式有几种类型

主要分为 饿汉式和懒汉式

特点

创建一个变量保存当前类的实例

私有化构造方法,不允许主动创建对象

开放一个静态方法去返回当前类的实例

2. 饿汉式介绍

饿汉式是指无论当前类是否被使用,在类加载的时候都有一个对象被创建等待使用。

代码实现

 1 /**
 2  * 单例模式--饿汉式
 3  * @Author:Ldy
 4  * @Date:2021/7/14
 5  */
 6 public class Singleton1 {
 7 
 8     private static Singleton1 singleton1 = new Singleton1();
 9 
10     private Singleton1(){}
11 
12     public static Singleton1 getInstance(){
13         return singleton1;
14     }
15 }
View Code

这种方式比较常用,容易实现,但是容易产生垃圾对象

多线程环境是否安全:安全

优点:没有加锁机制,执行效率高

缺点:在类加载时就创建了对象,浪费内存

3. 懒汉式介绍

懒汉式介绍是指只有在使用当前类时才去判断对象是否被创建,如果被创建则直接返回,反之则创建对象再返回。

这里主要介绍懒汉式中的 双重检查锁模式(DCL)

代码实现

 1 /**
 2  * 懒汉式 -- 双重检查锁模式(DCL)
 3  */
 4 public class Singleton2 {
 5     
 6     //volatile关键字的作用就是 为了解决以为重排序而导致读取不到完整的对象
 7     private volatile static Singleton2 singleton2 = null;
 8 
 9     private Singleton2(){}
10 
11     public static Singleton2 getSingleton2Instance() {
12         // a
13         if(singleton2 == null){
14             //JVN优化机制,先分配内存 再初始化
15             synchronized (Singleton2.class){
16                 if(singleton2 == null){
17                     singleton2 = new Singleton2(); // b
18                     //1. new ---> 申请内存空间
19                     //2. 完成属性的初始化(赋值)
20                     //3. 将对象内存地址交给变量singleton2来保存
21                     //存在的问题:假设此处有两个线程 a b, 此时b线程已经进入到b处,进行new Singleton2(),但是由于jvm优化机制,new一个对象其实
22                     //分为三步,需要第三步执行后 singleton2才不为空,由于jvm的重排序,第二步和第三步顺序不一定,假设先执行了第三步,虽然singleton2不为空,但是属性的初始化未完成,此时时间片用完了。到a线程执行 a线程判断singleton2不为空  后续直接使用该对象调用方法,那么结果就是报错。
23 
24                     //如何解决上诉问题:将singleton2变量加上volatile
25                 }
26             }
27         }
28         return singleton2;
29     }
30 
31 }
View Code

这种双重锁模式可以在多线程环境下安全运行而且还能保持高性能。实现起来较难

对应点的解释都在代码的注释中。

posted @ 2021-07-14 14:44  EchoLv  阅读(75)  评论(0)    收藏  举报