学习笔记--设计模式--单例模式
一、单例模式-懒汉式
2019-08-05 14:09:23
单例模式
定义:保证一个类只有一个实例,并提供一个全局访问点。
关键:构造器的私有化。
1、普通模式
1 public class LazySingleton { 2 private static LazySingleton lazySingleton = null; 3 //私有化构造器 4 private LazySingleton() { 5 } 6 public static LazySingleton getInstance() { 7 if (lazySingleton == null) { 8 lazySingleton = new LazySingleton(); 9 } 10 return lazySingleton; 11 } 12 }
存在问题:线程不安全。
解决方式:加锁
2、同步方法
public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { } //添加同步锁 public synchronized static LazySingleton getInstance() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; } }
存在问题:线程锁的范围过大,性能不佳。
3、同步代码块
public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { } public static LazySingleton getInstance() { if (lazySingleton == null) { synchronized (LazySingleton.class){ lazySingleton = new LazySingleton(); } } return lazySingleton; } }
存在问题:在多线程枪锁的过程,线程获得所得同时,其他线或许已经完成了初始化,所以可能会出现二次初始化
4、Double Check
public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { } public static LazySingleton getInstance() { if (lazySingleton == null) { synchronized (LazySingleton.class){ if(lazySingleton==null){ lazySingleton = new LazySingleton(); } } } return lazySingleton; } }
LazySingleTon 的初始化过程
1)分配内存给lazySingleton;
2)初始化对象 new LazySingleton();
3)设置lazySingleton指向刚刚分配的内存。
存在问题:在CPU执行代码的过程中,存在代码的二次重排,但是遵循intra-thread semantics
解决方式:
//使用volatile实现 安全的初始化,禁止重排序。保证内存可见性,可以访问共享内存。 private volatile static LazyDoubleCheckSingleton singleton = null;
5、静态内部类的单例模式
说明:
类在使用时才会被初始化的方式:
1)使用关键字 new 初始化类;
2)访问类或接口中的静态变量或对静态变量赋值;
3)调用类的静态方法;
4)反射
Class.forName(String className);
5) 初始化子类,父类也会被初始化。
public class StaticInnerClassSingleton { private static class InnerClass { private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton(); } private StaticInnerClassSingleton() { } public static StaticInnerClassSingleton getInstance() { //调用内部类的静态变量 return InnerClass.staticInnerClassSingleton;
} }
二、单例模式-饿汉式
1、普通模式
public class HungrySingleton {
//类加载时就完成初始化
//方式一:HungrySingleton hungrySingleTon = new HungrySingleton();
//方式二:通过静态代码块完成初始化。
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
2、保证序列化、反序列化之后仍然是同一个实例对象。
public class HungrySingleton implements Serializable {
//类加载时就完成初始化
//方式一:HungrySingleton hungrySingleTon = new HungrySingleton();
//方式二:通过静态代码块完成初始化。
private final static HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private static boolean flag =true;
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
//反序列化之后,仍然是同一个对象。
private Object readResolve(){
return hungrySingleton;
}
}
3、防止反射实例化对象
public class HungrySingleton implements Serializable { //类加载时就完成初始化 //方式一:HungrySingleton hungrySingleTon = new HungrySingleton(); //方式二:通过静态代码块完成初始化。 private final static HungrySingleton hungrySingleton; static { hungrySingleton = new HungrySingleton(); } private static boolean flag =true; private HungrySingleton(){ //针对类加载时就完成初始化,不可反射调用。 if(hungrySingleton!=null){ throw new RuntimeException("单例构造器禁止反射调用"); } } public static HungrySingleton getInstance(){ return hungrySingleton; } private Object readResolve(){ return hungrySingleton; } }
三、枚举单例模式(Effective Java 推荐)
// Effective Java 推荐 public enum EnumInstance { INSTANCE{ protected void test(){ System.out.println("test"); } }; //存放数据 private Object data; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public static EnumInstance getInstance(){ return INSTANCE; } }
四、容器化单例模式,管理多个单例模式
//适用场景:多租户数据库获取 public class ContainerSingleton { // 保证性能 private static Map<String,Object> singletonMap = new HashMap<String,Object>(); // 线程安全 // private static Map<String,Object> singletonMap = new Hashtable<>(); // 线程相对安全 // private static Map<String,Object> singletonMap = new ConcurrentHashMap<>(); public static void putInstance(String key,Object instance){ if(StringUtils.isNoneBlank(key)&&instance!=null){ //保证key的唯一性 if(!singletonMap.containsKey(key)){ singletonMap.put(key,instance); } } } public static Object getInstance(String key){ return singletonMap.get(key); } }
五、ThreadLocal 单例模式(借助ThreadLocal实现)
public class ThreadLocalInstance { private static final ThreadLocal<ThreadLocalInstance> threadlocadls = new ThreadLocal<ThreadLocalInstance>() { @Override protected ThreadLocalInstance initialValue() { return new ThreadLocalInstance(); } }; private ThreadLocalInstance() { } public static ThreadLocalInstance getInstance() { return threadlocadls.get(); } }

浙公网安备 33010602011771号