【Dongle】【软考】【设计模式】单例模式

    xiaoxiao2021-12-10  17

    特点

    一个类只有一个实例对象一般用在管理共享的资源上,例如线性池、缓存、对话框、偏好设置、注册表、日志的对象,及充当打印机、显卡等设备的驱动程序的对象,等等

     

    基本结构

    私有静态变量记录类的唯一实例私有构造器,只有类内才可以调用公共或保护型竞赛方法getInstance()实例化对象,提供全局访问点,并返回该对象

     

    基本代码

    Public class Singleton{ private static Singleton uniqueInstance; //私有静态变量记录类的唯一实例 private Singleton(){}; //私有构造器,只有类内才可以调用 public static Singleton getInstance(){ If(uniqueInstance==null){ //如果uniqueInstance为空,表示还没有实例化,实例化之后再返回 uniqueInstance=new Singleton(); //不存在就实例化,不需要永不实例化,即“延迟实例化” } return uniqueInstance; //表示已存在对象,返回该对象 } }

    存在问题

           存在多线程的问题,即多个线程同时进入if判断,然后先后创建多个对象,利用synchronized(同步)解决

    例如:

    public static synchronized Singleton getInstance(){}

           这样虽然避免了多个线程同时调用方法的问题,但是会产生另外一个比较严重的问题:就是每次调用这个方法的时候都需要同步,然而只有第一次执行这个方法才真正需要同步,故而每次都同步其实是一种累赘

    那么该如何解决同步累赘问题呢?有三种方法:

           

           第一种,如果getInstance()的性能对应用程序不是很关键,就什么都别做。即不会产生同步影响的就不需要加synchronized了,因为同步一个方法可能会造成程序执行效率下降,故而当频繁调用getInstance()的时候,就需要考虑了。

           第二种,使用“急切”创建实例,而不用延迟到实例化的做法。如果应用程序中是创建并使用单例实例,或者在创建或运行时方面的负担不太繁重,你可能想要机器创建此单例,如:

    Public classSingleton{ privatestatic Singleton uniqueInstance=new Singleton();//静态初始化器创建实例,保证线程安全 privateSingleton(){}; publicstatic Singleton getInstance() { return uniqueInstance; //已经有实例,直接使用它 } }

           即,在我需要使用实例之前就已经创建好了实例,使用时直接返回创建好的实例就OK

          第三种,用“双重检查加锁”,在getInstance()中减少使用同步。首先检查是否实例已经创建了,如果未创建,菜进行同步,这样一来,只有第一次会同步,正是我们想要的。

    Public classSingleton{ private volatile static Singleton uniqueInstance; //volatile确保多个线程正确地处理uniqueInstance变量 privateSingleton(){}; publicstatic Singleton getInstance(){ If(uniqueInstance==null){ //检查实例,如果不存在,就进入同步区块 Synchronized(Singleton.class){ //只有第一次才彻底执行这里 If(uniqueInstance==null){ uniqueInstance=new Singleton(); //进入区块后,再检查一次,如果仍是null,才创建实例 } } } returnuniqueInstance; } }

          如果性能是关心的重点,则双重锁的做法可以大大减少getInstance()的时间耗费。

     

     

    转载请注明原文地址: https://ju.6miu.com/read-700352.html

    最新回复(0)