设计模式:单例模式

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法,隐藏所有的构造方法,单例模式是一种对象创建型模式

举个常见的单例模式例子,我们日常使用的电脑上都有一个回收站,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。因此回收站是单例 模式的应用。 确保任何情况下都绝对只有一个实例。 ServletContext、ServletConfig、ApplicationContext  DBPool

饿汉式   

饿汉式单例是在类加载的时候就立即初始化,并且创建单例对象。绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题。

优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。 (用户体验<效率>和内存相对)

缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费了内存,有可能占着茅坑不拉屎。

还有另外一种写法,利用静态代码块的机制:

懒汉式    被外部类调用时才创建实例。

(1) Synchronized式,公共访问点加synchronized,保证线程安全,但效率降低。

 

 

掌握idea中多线程的调试模式

 

(2) 双重检查锁式,两个if判断,线程安全,提升了性能。

(3)内部类式,相当于饿汉式,线程安全,提升了性能。

反射破坏单例

改进:在构造方法上加上if判断

反序列化破坏单例

单例对象创建好,有时候需要将对象序列化然后写入到磁盘,下次使用时再从磁盘中读取到对象,反序列化转化为内存对象。反序列化后的对象会重新分配内存,即重新创建。那如果序列化的目标的对象为单例对象,相当于破坏了单例

 

注册式单例

注册式单例又称为登记式单例,就是将每一个实例都登记到某一个地方,使用唯一的标识获取实例。注册式单例有两种写法:一种为容器缓存,一种为枚举登记。

1)枚举登记,重点推荐

枚举对象不可能被类加载器加载多次,在JDK 枚举的语法特殊性,以及反射也为枚举保驾护航,让枚举式单例成为一种比较优雅的实现。

 

(2)容器缓存

 

ThreadLocal

将所有的对象全部放在 ThreadLocalMap 中,为每个线程都提供一个对象,实际上是以空间换时间来实现线程间隔离的,

在每个线程里都是可以获得到单例(伪单例)

 

单例模式的优点:

在内存中只有一个实例,减少了内存开销/可以避免对资源的多重占用/设置全局访问点,严格控制访问

单例模式的缺点:

没有接口,扩展困难。如果要扩展单例对象,只有修改代码,没有其他途径。

原文地址:https://www.cnblogs.com/LPJ-BLOG/p/12395969.html