单例模式在《设计模式》中的定义为“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”
1.饿汉式
饿汉式在类装载时便完成实例化,注意:单例模式的构造函数都是私有的。
public class HungryMan {
//静态常量,可以避免多次实例化
private final static HungryMan instance = new HungryMan();
private HungryMan(){ }
public static HungryMan getInstance() {
return instance;
}
}
2.懒汉式
懒汉式如果要保证线程安全,则要在getinstance()方法上加上synchronized关键字,并且还要在内部判断是否已经创建过实例。不过这样效率低,每次都要获取和释放锁。
public class LazyMan {
private static LazyMan instance;
private LazyMan(){}
public synchronized static LazyMan getInstance(){
if(instance==null){
instance = new LazyMan();
}
return instance;
}
}
3.双重检测
双重检测即优化版的懒汉式,不同的是将synchronized放在了方法内部,通过双重检测提升了效率。
为什么要使用volatile?因为对象的创建不具备原子性,所以要避免其重排序而导致空指针,同时也保证了可见性。
public class DoubleCheck {
private volatile static DoubleCheck instance;
private DoubleCheck(){}
public static DoubleCheck getInstance(){
//第一次检测
if(instance==null){
synchronized (DoubleCheck.class){
//第二次检测
if(instance==null){
instance = new DoubleCheck();
return instance;
}
}
}
return instance;
}
public static void main(String[] args) {
DoubleCheck instance = DoubleCheck.getInstance();
}
}
4.静态内部类
静态内部类中定义一个静态常量的实例,放在常量池中,这样就可以由jvm保证只生成一个实例。
public class StaticInterior {
private StaticInterior(){}
private static class SingletonInstance{
private static final StaticInterior INSTANCE = new StaticInterior();
}
public static StaticInterior getInstance(){
return SingletonInstance.INSTANCE;
}
}
5.枚举类
最简单,也是最推荐使用的
public enum EnumSingleton {
INSTANCE;
}