单例模式

什么是单例模式

单例模式是指在内存中只会创建且仅创建一次对象的设计模式.
在程序中多次使用同一个对象且作用相同时,为了防止频繁的创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象.

单例模式的类型

1.饿汉式:  在类加载的时候已经创建好单例对象,等待被程序使用.
2.懒汉式:  在真正需要使用对象时才去创建该单例类对象.

单例模式引用场景

1.Windows的任务管理器和回收站.
2.网站的计数器.
3.日志系统.
4.数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗.
5.多线程的线程池,方便对线程的控制.
6.HttpApplication,所有的HttpModule都共享一个HttpApplication实例.

单例模式的优劣势

优点:
   1.确保所有对象都访问的是一个实例.
   2.系统内存中只存在一个实例对象,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
   3.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
   4.提供了对唯一实例的受控访问.
缺点:
   1.不适用于变化的对象.
   2.单例类的职责过重,在一定程度上违背了“单一职责原则”.
   3.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时                  
     间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失.
   4.单例模式没有抽象层,扩展很困难.

单例模式的创建

饿汉式创建单例对象:

类在加载时会在堆内存中创建一个Singleton对象,当类被卸载时,Singleton对象也随之消亡.

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

饿汉式创建单例对象(双重检查锁模式):

加锁--实现线程安全问题,多线程时只会实例化一个Singleton对象.
双检查---实现性能优化,目标没有实例化对象则加锁创建,如果已实例化,不需要加锁直接获取.
volatile---防止指令重排,指令执行顺序和程序指明顺序一致,保证其内存可见性,每一时读取到的都是内存中的最新的值.

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

静态内部类创建单例对象:

只适用于静态域的情况,和饿汉式类似,但是Singleton类被加载时,singleton 不一定被初始化,只有调用getInstance()方法加载SingletonHolder 类时,才会被实例化.

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

枚举类创建单例对象:
Enum类内部Enum类型判定防止通过反射创建多个对象
Enum类通过读写对象类型和枚举名字将对象序列化,通过valueOf()方法匹配枚举名找到内存中唯一额对象实例,防止通过反序列化构造多个对象.

public class Singleton{
    private Singleton (){} 
    public enum SingletonEnum {  
        INSTANCE;  
        public void doSomething() {
            System.out.println("doSomething");
        } 
    }
    public static User getInstance(){
        return SingletonEnum.INSTANCE.doSomething();
    }
}

实战案例

引用参考博客地址:
https://blog.51cto.com/14230003/2512603?source=dra

posted @ 2020-08-05 11:29  程半仙  阅读(17)  评论(0)    收藏  举报