单例模式
定义:一个类只有一个实例
分类:单例模式可分为三大类-八小类:
- 饿汉式
- 静态常量(推荐)
- 静态代码块(推荐)
- 懒汉式
- 线程不安全
- 线程安全,同步方法
- 线程安全,同步代码块
- 双重检查(推荐)
- 静态内部类(推荐)
- 枚举 (推荐)
对比:
| 模式 | 描述 | 方式 | 优点 | 缺点 | 是否推荐 |
|---|---|---|---|---|---|
| 饿汉模式(2) | 不管需不需要用到实例都要去创建实例 | 1. 静态常量 1. 静态代码块 |
线程安全 | 浪费内存(没用到的情况下) | 推荐 |
| 懒汉模式(5) | 需要用到创建实例了程序再去创建实例 | 普通饿汉实现 | 线程不安全 | 不推荐 | |
| 同步方法 | 线程安全 | 消耗性能(每次都要锁) | 不推荐 | ||
| 同步代码块 | 减少了同步方法的性能消耗 | 线程不安全 | 不推荐 | ||
| 双重检查 | 线程安全 | 推荐 | |||
| 静态内部类 | 线程安全 | 推荐 | |||
| 枚举模式(1) | - | - | 1. 解决线程同步 2. 防止反序列化 原因:由于枚举没有构造方法,不会被反射 反射原理:类的class文件加载到内存,反射(反序列化的方式)new一个实例(前提要有构造方法) |
推荐(完美中的完美) |
剖析原理
分析实现步骤
- 构造器私有化
- 创建对象实例
-
代码实现
饿汉模式
静态常量
/*** 单例 - 饿汉模式 - 静态常量*/public class SingletonByStaticConst {//私有化构造器private SingletonByStaticConst() {}//静态常量private final static SingletonByStaticConst INSTANCE = new SingletonByStaticConst();//公共获取实例方法public static SingletonByStaticConst getInstance(){return INSTANCE;}}
静态代码块
/** * 单例 - 饿汉 - 静态代码块 */ public class SingletonByStaticBlock { //构造器私有化 public SingletonByStaticBlock() {} //静态代码块 private static SingletonByStaticBlock INSTANCE; static{ INSTANCE = new SingletonByStaticBlock(); } //公共获取实例方法 public static SingletonByStaticBlock getInstance(){ return INSTANCE; } }懒汉模式
线程不安全
/** * 单例 - 懒汉 - 线程不安全 */ public class SingletonByLazyUnsafe { private static SingletonByLazyUnsafe instance; //私有化构造器 private SingletonByLazyUnsafe() {} //公共获取实例方法 public static SingletonByLazyUnsafe getInstance(){ if(null == instance){ //存在线程安全问题,不推荐 instance = new SingletonByLazyUnsafe(); } return instance; } }同步方法
```java /**
单例 - 懒汉 - 同步方法 */ public class SingletonByLazySyncMethord {
private static SingletonByLazySyncMethord instance; //私有化构造器 private SingletonByLazySyncMethord() {} //公共获取实例方法 public static synchronized SingletonByLazySyncMethord getInstance(){ if(null == instance){
instance = new SingletonByLazySyncMethord();} return instance; } }
<a name="LdyGA"></a>
### 同步代码块
```java
/**
* 单例 - 懒汉 - 同步代码块
*/
public class SingletonByLazySyncBlock {
private static SingletonByLazySyncBlock instance;
//私有化构造器
private SingletonByLazySyncBlock() {}
//公共获取实例方法
public static SingletonByLazySyncBlock getInstance() {
if (null == instance) {
//解决了每次判锁的性能问题,但存在线程不安全问题
synchronized (SingletonByLazySyncBlock.class) {
instance = new SingletonByLazySyncBlock();
}
}
return instance;
}
}
双重检查
/**
* 单例 - 懒汉 - 双重检查
*/
public class SingletonByLazyDoubleCheck {
private static SingletonByLazyDoubleCheck instance;
//私有化构造器
private SingletonByLazyDoubleCheck() {}
//公共获取实例方法
public static SingletonByLazyDoubleCheck getInstance() {
if (null == instance) {
synchronized (SingletonByLazyDoubleCheck.class) {
if(null == instance){
instance = new SingletonByLazyDoubleCheck();
}
}
}
return instance;
}
}
静态内部类
/**
* 单例 - 懒汉 - 静态内部类
*/
public class SingletonByLazyStaticInner {
private static SingletonByLazyStaticInner instance;
//私有化构造器
private SingletonByLazyStaticInner() {}
//静态内部类,初始化时不加载,只有使用的时候才会被加载
private static class SingletonInstance{
private static final SingletonByLazyStaticInner INSTANCE = new SingletonByLazyStaticInner();
}
//公共获取实例方法
public static SingletonByLazyStaticInner getInstance() {
return SingletonInstance.INSTANCE;
}
}
枚举
/**
* 单例 - 枚举
*/
public enum SingletonByEnum {
INSTANT;
}
框架或项目源码分析
JDK中java.lang.Runtime类使用了单例,采用了饿汉模式的静态常量方式
应用场景
- 重量级对象(需要频繁的进行创建和销毁对象)
- 经常用到的对象
- 工具类对象
- 频繁访问数据库或文件的对象,例如:数据源、session工厂
