单例模式(Singleton mode)
一、概念
采取一定的方法保证在整个软件系统中 ,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
一、应用场景
三、设计模式写法(八种)
1.饿汉式 (静态常量)
1 2 3 4 5 6 7 8 9
| class Singleton { private Singleton() {}
private final static Singleton instance = new Singleton();
public static Singleton getInstance() { return instance; } }
|
1. 构造器私有化
2. 类的内部创建对象
3. 向外暴露一个静态公共方法(getInstance)
4. 代码实现
2. 饿汉式(静态代码块)
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Singleton { private Singleton() {}
private static Singleton instance; static { instance = new Singleton(); }
public static Singleton getInstance() { return instance; } }
|
小结:饿汉式说白了就是创建类的时候创建实例,这样可以保证线程安全,但是如果项目中没有用到就会造成资源浪费
3. 懒汉式(线程不安全)
1 2 3 4 5 6 7 8 9 10 11 12
| class Singleton { private Singleton() {}
private static Singleton instance;
public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
|
4. 懒汉式(线程安全,同步方法)
1 2 3 4 5 6 7 8 9 10 11 12
| class Singleton { private Singleton() {}
private static Singleton instance;
public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
|
这种方式会效率太低,不推荐使用
5. 懒汉式(线程安全,同步代码块)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Singleton { private Singleton() {}
private static Singleton instance;
public static synchronized Singleton getInstance() { if (instance == null) { synchronized (this.class){ instance = new Singleton(); } } return instance; } }
|
不能起到线程同步的作用,在实际中不能使用
6.双重检查(Double Check)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Singleton { private Singleton() {}
private volatile static Singleton instance;
public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
|
两次 if (instance == null) 解决线程安全问题,同时解决懒加载问题,推荐使用
7.静态内部类
1 2 3 4 5 6 7 8 9 10 11
| class Singleton { private Singleton() {}
private static class SingletonInstance{ private static final Singleton INSTANCE = new Singleton(); }
public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
|
这种方式 采用了类加载机制保证初始化实例时只有一个线程
避免了线程不安全,利用静态内部类特点实现延迟加载,效率高,推荐使用
8. 枚举
不仅能避免多线程同步问题,而且还能防止反序列话重新创建新的对象提倡使用
四、小结
- 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
- 想实例化一个单例类的时候,使用相应的获取方法,而不是使用 new
- 单例模式使用的场景
- 需要
频繁进行创建和销毁的对象(各种池)
- 创建对象耗时过多或耗费资源过多,但是又经常用到的对象、工具类对象、频繁访问的数据库、文件的对象(数据源、session工厂等)
在实际使用中,多使用饿汉式(两种方法)、双重检查、静态内部类、枚举