单例模式(八种单例模式)

什么是单例?

确保一个类在任何情况下(任何情况:多线程、并发、反射调用构造器)只有一个实例,并提供一个全局访问点。单例会因此其所有的方法、属于创建型模式。

单例的几种写法?

懒汉、饿汉、枚举、double check 、内部类。
一、饿汉式:不管用不用,都先赋值。优点:线程安全、逻辑简单、空间换时间;缺点:如果这种写法被大量使用,导致内存开销增加。
二、懒汉式:即用即赋值,不调用不赋值。第一次使用时先判断,有没有,没有就创建,第二次时就直接返回。优点:资源占用少、逻辑简单;缺点:线程不安全。
三、简单写法(synchronized加在方法上,锁的是整个类):
缺点:性能低,因为阻塞,线程始终处于等待。
四、双重验证写法(synchronized锁加在方法内,在两次判断之间):
缺点:可读性下降,不够优雅。
五、LazyInnerClassSingleton:
优点:代码优雅,利用天生的语法优势

以上5种写法共同缺点:
private Singleton(){}是一个假象,使用暴力反射,getDeclered方法后,会获取到对象,在new Instance(),会得到多个对象,违背单例。
解决方法:
六、1.构造方法中加上一个if判断,判断Lazy类不为空,为空时,抛出运行时异常;
六、2.注册式单例(容器式注册、枚举式注册):

  • 枚举式注册基于key-value形式,每个key对应一个实例,被加载前就已经被赋值,赋值可以做成动态的,类似懒汉式,底层实际还是通过volatile进行修饰。通过暴力反射时获取不到,因为枚举式注册,没有无参构造。
    七、Spring Ioc容器就是单例的实现,容器式单例:
    public class ContainerSingleton { `` private ContainerSingleton(){} private static Map<String , Object> map=new HashMap<>(); public static void putInstance(String key, Object value){ if (key!=null && !key.isEmpty() && value!=null){ if (!map.containsKey(key)){ map.put(key,value); } } } public static Object getInstance(String key){ return map.get(key); } }
    但是HashMap线程不安全,使用HashTable会影响性能,忽略反射、序列化等问题,可以使用。
    代码引用于:https://blog.csdn.net/zhangxiangliang2/article/details/91896101
    八、ThreadLocal单例:
    线程局部变量,是一种多线程间并发访问变量的一种解决方案,与其synchronized加锁的方式不同,它完全不提供锁,以空间换时间,多线程下为每个线程提供实例,以保障线程安全,不能保证程序唯一,但是能保证线程唯一,并且每个线程中拿到的实例时同一个,不同线程中拿到的不同。
public class ThreadLocalInstance  {    
	private static final ThreadLocal<ThreadLocalInstance> 		threadLocalInstance= new ThreadLocal<ThreadLocalInstance>(){                		   	 @Override
	protected ThreadLocalInstance initialValue() {                      return new ThreadLocalInstance();                
	}            };     
	private ThreadLocalInstance(){}     
	public static ThreadLocalInstance getInstance(){       
	 return threadLocalInstance.get();     
	}
}
原文链接:https://blog.csdn.net/zhangxiangliang2/article/details/91896101
  • 两个线程打印相同结果:

1.线程按顺序执行(正常);
2.线程同时进入,后者覆盖前者。

  • 两个线程打印不同结果:

1.线程同时进入(先后执行之后的逻辑)。

Volatile关键字

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值