使用场景:在容器中一个对象只存在一个实例。

目的:1.防止堆中内存过多。影响效率。

2.无论怎么使用,都规定使用同一个对象

实例:获取序列号,任务管理器,计数器等

缺点没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

代码:

1.饿汉式(线程安全,调用效率高,但是不能延时加载,会占用内存)

public class Singleton {  
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}

2.懒汉式(线程安全,调用效率不高,但是能延时加载)

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

3.双检锁/双重校验锁 延时加载 比较复杂 不建议使用

public class Singleton {  
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

4.静态内部类 延时加载 只适用于静态域的情况

public class Singleton {  
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

5.枚举 非延时加载

public enum Singleton {  
INSTANCE;
public void whateverMethod() {
}
}

一般情况下,建议使用饿汉模式,只有在要明确实现 lazy loading 效果时,才会使用第静态内部类方式。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。