天天看点

小学生之单例模式单例模式

单例模式

Singleton Pattern ,是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。属于创建者模式

1、饿汉式

优点:执行效率高

缺点:类加载就初始化,不管用不用都占用着空间,浪费内存

public class Singleton {
    private static final Singleton singleton = new Singleton();

    private Singleton(){}

    public static Singleton getInstance(){
        return singleton;
    }
}
           

2、懒汉式

优点:解决了恶汉式的无赖

缺点:并发过大时,会出现线程不安全

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

3、双重检查锁

优点:解决了懒汉式的线程不安全问题

缺点:并发过大时,会导致程序性能下降。

public class Singleton {
	// volatile 禁止重排,避免出现重排 实例未加载
    private static volatile Singleton singleton = null;
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
           

4、静态内部类

  • 解决饿汉的内存浪费、双重锁的性能问题,
  • 缺点:内部类不能接受传参数
public class Singleton { 
    private Singleton(){}

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

5、防反射

  • 无敌版
public class Singleton { 
    private Singleton(){
        if (Lazy.SINGLETON != null) {
            throw new RuntimeException("不可以哦")
        }
    }

    public static final Singleton getInstance(){
    	return lazy.SINGLETON;
    }
    private static class Lazy{
        private static final Singleton SINGLETON = new Singleton();
    }
}
           

6、注册式

  • 枚举实现
public enum Singleton {
	INSTANCE;

	public static Singleton getInstance() {
		return INSTANCE;
	}
}
           
  • 容器实现
public class Singleton {
	private Singleton() {}

	private static Map<String, Object> ioc = new ConcurrentHashMap<>();

	public static Object getBean(String className) {
		synchronized (ioc) {
			if (!ioc.containsKey(className)) {
				Object obj = null;
				try {
					obj = Class.forName(className).newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
				return obj;
			} else {
				return ioc.get(className);
			}
		}
	}
}
           

7、线程实现

  • 仅能保证当前线程是唯一的
public class Singleton {
	private static final ThreadLocal<Singleton> threadLocalSingleton 
        		= new ThreadLocal<Singleton>() {
                     @Override
                     protected Singleton initialValue() {
                        return new Singleton();
                     }
    			};

	private Singleton() {}

	private static Map<String, Object> ioc = new ConcurrentHashMap<>();

	public static Object getBean(String className) {
		 return threadLocalSingleton.get();
	}
}

           

ps:

还有一种破坏单例:序列化。

解决方案:重写readResolve方法