0%

设计模式之单例模式(二)

前言

前面我们介绍了单例模式的饿汉模式,其实饿汉式很好理解,形象的记忆就是不管怎么样,先把内存吃掉再说。本着贪多嚼不烂的原则,我们今天来看看懒汉式,这个懒汉式就有三种不同的形式。当然还是理解为主。

懒汉式(线程不安全)

在同一个线程中运行,这个方法没有问题。我们先看代码,后面再来看看这个懒汉式的优缺点。

1
package com.yubulang.type03;
2
3
public class Singleton {
4
    private Singleton() {
5
    }
6
7
    private static Singleton instance;
8
9
    // 提供一个静态的公有方法,当使用到该方法时,才去创建instance
10
    // 懒汉式1 这个因为懒,懒得线程都不安全了
11
    public static Singleton getInstance() {
12
        if (instance == null) {
13
            instance = new Singleton();
14
        }
15
16
        return instance;
17
    }
18
}

优缺点:

  • 起到了 Lazy Loading 效果,但是只能在单线程下使用。
  • 如果在多线程下,一个线程进入了 if (instance == null) 判断语句块,还未来得及往下执行,另一个进程也通过了这个判断语句,这时便会产生多个实例。所以在多线程的情况下不要使用这种方式
  • 结论:在实际开发中,不要使用这种模式

懒汉式(线程安全,同步方法)

为了得到一个线程安全的代码,我们加入了 synchronized 代码,但是这个方法有利有弊。

1
package com.yubulang.type04;
2
3
public class Singleton {
4
    private Singleton() {
5
    }
6
7
    private static Singleton instance;
8
9
    // 提供一个静态的公有方法,当使用到该方法时,才去创建instance
10
    // 懒汉式2 为了解决线程安全问题,我们加入同步代码
11
    public static synchronized Singleton getInstance() {
12
        if (instance == null) {
13
            instance = new Singleton();
14
        }
15
16
        return instance;
17
    }
18
}

优缺点:

  • 解决了线程不安全问题
  • 效率太低了,每个线程在想获得类的实例时候,执行 getInstance() 方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低。
  • 结论:在实际开发中,不推荐使用这种方法

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

其实这种写法,是白给,因为和第一个中模式一样,我们先看代码再看总结

1
package com.yubulang.type05;
2
3
public class Singleton {
4
    private Singleton() {
5
    }
6
7
    private static Singleton instance;
8
9
    // 提供一个静态的公有方法,当使用到该方法时,才去创建instance
10
    // 懒汉式3 为了解决线程安全问题,我们加入同步代码
11
    public static Singleton getInstance() {
12
        if (instance == null) {
13
            synchronized (Singleton.class) {
14
                instance = new Singleton();
15
            }
16
        }
17
18
        return instance;
19
    }
20
}

优缺点:

  • 这种方式,本意是想引出下面的改进版本,因为前面同步方法效率太低,改为同步产生实例化的代码块
  • 但是这种同步方式并不能起到线程同步的作用。跟第三种实现方式遇到的情景一致,假如一个线程进入了 if (instance == null) 判断语句块,还未来得及往下执行,另一个进程也通过了这个判断语句,这时便会产生多个实例。所以在多线程的情况下不要使用这种方式
  • 结论:在实际开发中,不要使用这种模式

总结

其实懒汉式大叫了解一下就好了。实际开发中并不怎么使用,让它存在主要是为了引出下面的的一些方法。PEACE!!!