单例模式

单例模式有两个特点:

  1. 保证一个类只有一个实例
  2. 为该实例提供一个全局访问节点

为什么要使用单例模式:

通常是为了集中管理某种共享资源(如数据库,文件等)。

单例模式的实现步骤:

  1. 将默认构造函数设置为私有;
  2. 新建一个静态构建方法作为构造函数。 该函数会调用私有构造函数来创建对象, 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。

饿汉式

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

懒汉式

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

双重检查锁

public class SingletonObj {
    private static volatile SingletonObj instance;
    private SingletonObj() {}
 
    public static SingletonObj getInstance() {
        if (instance == null) {
            synchronized(SingletonObj.class) {
                if (instance == null) {
                    instance = new SingletonObj();
                }
            }
        }
    }
}

为了提高懒汉式的性能,只有在实例不存在的情况下才进行加锁。 对instance对象添加volatile关键字,是为了解决有序性(指令重排)问题。不加的话,JVM 可能在构造函数内的属性还未初始化完成时,就返回对象,会导致其他线程可能会获取到不完整的对象。

静态内部类实现

public class SingletonObj {
    private SingletonObj() {}
 
    private static class InstanceHolder {
        private static SingletonObj instance = new SingletonObj();
    }
 
    public static SingletonObj getInstance() {
        return InstanceHolder.instance;
    }
}

枚举类实现

public class SingletonObj {
    private SingletonObj() {}
 
    private enum Singleton {
        INSTANCE;
 
        private static SingletonObj instance;
        
        Singleton() {
            instance = new SingletonObj();
        }
 
        private SingletonObj getInstance() {
            return instance;
        } 
    }
 
    public static SingletonObj getInstance() {
        return Singleton.INSTANCE.getInstance();
    }
}