1、懒汉式
2、DCL双重锁检查式单例 : 最常用的单例模式书写方式
3、容器式
4、枚举式 : 避免反序列化创建新的实例的问题,写法简单效率高
public class SingleInstanceTest{
private static SingleInstanceTest instance = null;
//注意:单例模式的构造方法要私有化
private SingleInstanceTest() {
}
//1、懒汉模式
//使用synchronized将getInstance方法变为一个同步方法,使其在多线程情况下也可以保证对象的唯一性
//缺点:即使instance已经被初始化,每次调用getInstance都会进行同步,会产生额外的资源消耗而且第一次加载的时候反应稍慢。
public static synchronized SingleInstanceTest getInstance1() {
if (instance == null) {
instance = new SingleInstanceTest();
}
return instance;
}
//2、一般情况下使用的单例模式:Double Check Lock(DCL)
//优点:资源利用里高,第一次执行getInstance2时单例对象才会被实例化,效率高
//缺点:第一次加载时反应稍慢
public static SingleInstanceTest getInstance2() {
if (instance == null) {//避免不必要的同步,如果有这个对象就直接返回
synchronized (SingleInstanceTest.class) {//防止出现DCL失效问题,我觉得不必深究
if (instance == null) {
instance = new SingleInstanceTest();
}
}
}
return instance;
}
//3、容器实现单例模式
private static Map<String, Object> objectMap = new HashMap<String, Object>();
//将对象添加到容器
public static void registerService(String key, Object instance) {
if (!objectMap.containsKey(key)) {
objectMap.put(key, instance);
}
}
//根据key值取出对象
public static Object getService(String key) {
return objectMap.get(key);
}
//以上三种单例模式的实现方法,核心原理都是将构造函数私有化,并且通过静态方法获取一个唯一的实例并且在获取的过程中要保证线程安全
//上面三种单例模式会在反序列化的情况下重新创建对象,如果要避免这种情况可以使用枚举类型的单例
}
//特殊单例模式:枚举单例,可以防止反序列化导致重新生成实例对象
//枚举实例的创建是线程安全的,并且在任何情况下都是一个单例
//上面三种单例模式会在反序列化的情况下重新创建对象
// 而使用枚举类型的单例可以避免此问题
public enum EnumSingleInstance {
INSTANCE;
public void function1(){
}
}