浅谈单例模式的几种实现

单例模式(来自菜鸟教程)

单例模式(Singleton Pattern)是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式的要求

  • 构造方法必须私有化(确保只有自己能创建)
  • 以静态方法返回实例(外界不能通过new来获取到对象)
  • 确保对象实例只有一个(只对类进行一次实例化,以后都直接获取第一次实例化的对象)

单例模式的实现

1、懒汉式(线程不安全)

描述:这种方式是最基本的实现方式,但是不支持多线程。因为没有加锁,在多线程不能正常工作

1
2
3
4
5
6
7
8
9
10
11
12
13
//懒汉式(线程不安全)
public class Singleton {
private static Singleton instance;

private Singleton (){}

public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

2、懒汉式(线程安全)

描述:能够在多线程下正常工作,但是,效率极低

1
2
3
4
5
6
7
8
9
10
11
12
13
//懒汉式(线程安全)
public class Singleton {
private static Singleton instance;

private Singleton (){}

public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

3、双重校验锁(DCL,即double-checked locking)(线程安全)

描述:对懒汉式(线程安全)的优化,采用双锁的机制,安全且在多线程情况下能保持高性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//双重校验锁
public class Singleton {
private volatile static Singleton instance;

private Singleton() {

}

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

4、饿汉式(线程安全)

描述:这种方式比较常用,但容易产生垃圾对象

1
2
3
4
5
6
7
8
9
10
11
12
//饿汉式
public class Singleton {
private static Singleton instance = new Singleton();

private Singleton() {

}

public static Singleton getInstance() {
return instance;
}
}

5、静态内部类(线程安全)

描述:这种方式达到跟双重校验锁一样的效果,这种方式只适用于静态域的情况,双重校验锁可在实例域需要延迟初始化时使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

private Singleton() {

}

public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

6、枚举(线程安全)

描述:这种方式还没有被广泛采用,但是这种实现是单例模式的最佳方法。更简洁、自动支持序列化机制、绝对防止多次实例化

1
2
3
4
5
6
7
8
//枚举
public enum Singleton {
INSTANCE;

public void whateverMethod() {

}
}

总结

一般情况下,不建议使用第1种和第2种懒汉方式,建议使用第4种饿汉方式。只有在明确实现lazy loading时,才会使用第5种静态内部类方式。如果涉及到反序列化创建对象时,可以使用第6种枚举方式。如果有其他需求,可以考虑使用第3种双重校验锁方式。

PS:开始面临着春招,好多面经都有说到设计模式。最常见的面试题就是讲一讲单例模式的实现和理解,所以我写一下,加深我对单例模式的理解和印象。觉得对你有帮助的话可以点点赞,谢谢啦~~~

-------------本文结束感谢您的阅读-------------

本文标题:浅谈单例模式的几种实现

文章作者:god-jiang

发布时间:2020年02月08日 - 12:37:17

最后更新:2020年02月08日 - 13:12:00

原始链接:https://god-jiang.github.io/2020/02/08/浅谈单例模式的几种实现/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

创作不易,您的支持就是我坚持的动力,谢谢大家!
0%