图解设计模式(2) 单例模式

目录

一、什么是单例模式 

二、单例模式的实现

1. 饿汉式

2. 懒汉式

3.双重检测锁式

4.静态内部类式

5.枚举式


一、什么是单例模式 

    单例模式,就是使一个类只能产生一个实例。

    应用场景:

  •   当一个对象的产生需要比较多的资源时,则可以在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。
  •   应该只有一个实例的情形,如系统任务管理器、网站计数器等,也可以使用单例模式保证只产生一个实例。

    常见的单例模式的实现方式有:

    主要:

  •     饿汉式(线程安全,调用效率高。 但不能延迟加载)
  •     懒汉式(线程安全,但调用效率不高,可以延迟加载)

    其他:

  •     双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
  •     静态内部类式(线程安全,调用效率高, 而且可以延迟加载)
  •     枚举式 (线程安全,但调用效率不高,也不能延迟加载)

二、单例模式的实现

1. 饿汉式

     饿汉式,指像一个饿汉一样,等不及了,管他三七二十一,一上来就创建实例。

     写单例模式的两个要点:

     (1)将构造器设为private, 这样在外部就不能调用了。

     (2)提供一个public static的方法,使外部可以通过此方法获取到实例。

public class MySingleton {
    private static MySingleton instance = new MySingleton(); //一上来就创建实例

    private MySingleton(){} //私有化构造器
	
    //public static方法提供获取途径
    public static synchronized MySingleton getInstance(){ 
        return instance;
    }
}

2. 懒汉式

    懒汉式,就是像一个懒汉一样,一动都懒得动,不到最后一刻就不创建实例。

public class MySingleton {
    private static MySingleton instance = null;

    private MySingleton(){} //私有化构造器
    
    //public static方法提供获取途径。 直到调用的那一刻才创建实例
    public static synchronized MySingleton getInstance(){ 
        if (null == instance) {
            instance = new MySingleton();
        }
        return instance;
    }
}

懒汉式和饿汉式各有优劣(饿汉式天然同步,懒汉式延迟加载),我们寻找其他的途径就对它们两个的优劣进行取长补短。

3.双重检测锁式

     因为编译器和CPU的优化,会导致指令的重排序。因此有可能出现先给instance分配内存,而new instance还没有产生实例的情况,此时instance==null不成立, 但是如果return instance而由外面对其操作,则会产生错误。

为了防止重排序,对instance 加上volatile,还使用了双重检测机制。

public Class Singleton{
    private static volatile Singleton instance;   //用volatile防止重排序
    
    public static Singleton getInstance(){
        if(null == instance){
            synchronized (Singleton.class){ //在这里加锁是为了尽量减小加锁区域
            	//双重检测,为了防止JVM指令重排序导致先new而使得instance==null不成立
                if(null == instance){          
                    instance = new Singleton();	
                }	
            }	
        }	
        return instance;
    }	
}

4.静态内部类式

  要点

  (1)外部类没有static对象,不会像饿汉式一样立即加载对象;

  (2)只有当调用getInstance时才会加载静态内部类。加载类时线程是安全的。并且instance是static final类型,保证了内存中只有一个对象实例存在且只能被赋值一次,保证了线程的安全性。

     静态内部类式单例兼备了并发高效性和延迟加载的优点。

public class MySingleton{
    private static class InnerClass{
        private static final MySingleton instance = new MySingleton(); 
    }
    
    private MySingleton(){}
    
    public static MySingleton getInstance(){
        return InnerClass.instance;
    }   
}

5.枚举式

  枚举本身就是单例模式,由JVM从根本上提供保障,避免了通过反射和反序列化调用和私有构造器的漏洞。 但不能延迟加载。

public enum MySingleton{
 
    //定义枚举的一个元素,就是一个单例
    INSTANCE;
    
    //添加其他的操作
    public void func(){    
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值