单例模式
定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例(以静态方法)
应用
- 整个项目中需要一个共享访问点或者共享数据
- 创建一个对象需要消耗的资源过多,如要访问IO和数据库资源等
- 需要定义大量静态常量和静态方法的环境
优点
- <font color=#2a3342>减少内存开支</font>
在内存中只有一个实例,减少对象频繁创建和销毁的性能开销 - <font color=#2a3342>避免对资源多重占用</font>
由于只有一个实例存在,避免对同一资源文件的同时操作
单例模式<font color=#3480d7>6</font>种实现
1. 饿汉模式
public class Singleton {
// 第一次加载到内存中就会被初始化,不管需不需要都给一个实例
// 所以创建实例本身是线程安全的
private static final Singleton instance = new Singleton();
// 构造函数
private Singleton() {
}
// 静态方法获取实例
public static Singleton getInstance() {
return instance;
}
}
2. 懒汉模式
public class Singleton {
// 一开始不新建实例,需要时再创建
private static Singleton instance = null;
private Singleton() {
}
// 线程不安全,多个线程调用该方法时还有可能产生多个实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3. 线程安全的懒汉模式
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
// 添加关键字synchronized
// 同一时刻最多只有一个线程调用该方法,结果效率不是很好
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4. 双重检验锁
public class Singleton {
// JDK1.5或之后版本添加关键字volatile,防止编译器自行优化代码
private /**volatile**/ static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
// 第一重检验锁,如果不为空直接返回实例
if (instance == null) {
synchronized (Singleton.class) {
// 第二重检验锁,因为可能有多个线程进入
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
5. 静态内部类
public class Singleton {
// 线程安全,饿汉式静态内部类
// 就算Singleton类被装载了,instance不一定被初始化,因为Inner类没有被主动使用
private static class SingletonInner {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonInner.INSTANCE;
}
}
6. 枚举
/**
* 通过Singleton.INSTANCE来访问实例对象
* 而且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题
*/
public enum Singleton{
// 实际上做了
/**new Enum<Singleton>("INSTANCE", 0)**/
INSTANCE;
// 其他方法
}