一些单例模式的对比
结论先行
Lazy 初始化 |
多线程 安全 |
优点 | 缺点 | |
---|---|---|---|---|
饿汉式 | 是 | 是 | 没有加锁,执行效率会提高 | 类加载时就初始化,浪费内存 |
懒汉式 | 否 | 是 | 第一次调用才初始化,避免内存浪费 | 必须加锁 synchronized 才能保证单例,但加锁会影响效率 |
双重校验锁 的懒汉式 |
是 | 是 | 安全且在多线程情况下能保持高性能 | getInstance() 的性能对应用程序很关键 |
静态内部类 | 是 | 是 | -达到 lazy loading 效果 -只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance |
可以被反射破坏 |
枚举类 | 否 | 是 | -支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化 -不能被反射破坏 |
实现代码:
饿汉式
/**
* 饿汉式实现单例模式
*/
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
懒汉式
/**
* 懒汉式单例模式(线程安全)
*/
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重校验锁的懒汉式
/**
* 懒汉式单例模式(同步代码块双重检查) 此处注意引用需要用volatile修饰,防止指令重排序
*/
public class Singleton {
private Singleton() {
}
private static volatile Singleton instance;
public static Singleton4 getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
静态内部类
/**
* 静态内部类实现单例模式
*/
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder .INSTANCE;
}
}
枚举类
/**
* 枚举实现单例模式
*/
public enum Singleton {
INSTANCE;
public void whateverMethod() {
//方法体
}
}
//想要使用时
public static void main(String[] args){
Singleton.INSTANCE.whateverMethod();
}
关于单例模式
用来创建独一无二的,只有一个实例对象,是一种最简单的设计模式。
特点:
- 一个类只能有一个实例
- 自己创建这个实例
- 整个系统都要使用这个实例
对于有一些对象,其实例我们只需要一个,比方说:线程池、缓存(cache)、日志对象等,如果创建多个实例,就会导致许多问题产生,比如资源使用过量、程序行为不可控,或者导致不一致的结果。