ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

23种常用设计模式(一)单例模式

2020-06-06 13:02:23  阅读:237  来源: 互联网

标签:Singleton 23 private single static 单例 线程 设计模式


一、单例模式的定义

单例模式 :确保某个类只有一个实例,且自行实例化并向整个系统提供这个实例。

二、单例模式的优缺点及应用场景

优点:单例模式在内存中只有一个实例,大大减少了内存开支,特别是一个对象需要频繁地创建、销毁时,单例模式的优势就非常明显。单例模式可以在系统设置全局的访问点,优化和共享资源访问。

缺点:单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。

使用场景:在一个系统中,要求一个类有且仅有一个对象,或者创建一个对象需要消耗的资源过多,都可以使用单例模式;如spring中的bean对象默认是单例模式。

三、单例模式示例代码

3.1、饿汉式

//饿汉式单例,在类初始化时创建,线程安全
public class Singleton {
	//构造方法私有化,防止外界创建
    private Singleton() {}
    //创建对象
    private static final Singleton single=new Singleton();
    //获取实例对象
    public static Singleton getInstance() {
        return single;
    }
} 

3.2、懒汉式

//懒汉式单例.在第一次调用的时候创建,线程不安全
public class Singleton {
	//构造方法私有化,防止外界创建
    private Singleton() {}
    private static final Singleton single=null;//单例对象
    
    public static Singleton getInstance() {
    	if (single == null) {  
             	single = new Singleton();
         	}  
        return single;
    }
} 

懒汉式单例模式在低并发的情况下尚不会出现问题,若系统压力增大,并发量增加时则可能在内存中出现多个实例,破坏了最初的预期。

如一个线程A执行到singleton= new Singleton(),但还没有获得对象(对象初始化是需要时间的),第二个线程B也在执行,执行到(singleton == null)判断,那么线程B获得判断条件也是为真,于是继续运行下去,线程A获得了一个对象,线程B也获得了一个对象,在内存中就出现两个对象!

要实现线程安全,有以下三种方式:

1、在getInstance方法上加锁同步

public class Singleton {
	//构造方法私有化
    private Singleton() {}
    private static final Singleton single=null;//单例对象
    
    public static synchronized Singleton getInstance() {//同步锁
    	if (single == null) {  
             	single = new Singleton();
         	}  
        return single;
    }
}

此方法虽保证了线程安全,但每次调用都要获取锁,对性能有很大影响。

2、双重检查

public class Singleton {
	//构造方法私有化
    private Singleton() {}
    //volatile保证可见性和禁止指令重排序
    private volatile static Singleton single=null;
    
    public static Singleton getInstance() {
    	if (single == null) { // 第一重检查锁定
			synchronized (Singleton.class) {//同步锁
				if (single == null) { // 第二重检查锁定
             		single = new Singleton();
         		}
         	}  
         }
        return single;
    }
}

此方法比第一种好一些,只有第一次访问(还未创建对象)才需要获取锁。

3、静态内部类

  public class Singleton {  
    private static class LazyHolder {
    	//被调用时加载
       private static final Singleton single= new Singleton();  
    }  
    private Singleton (){}  
    
    public static Singleton getInstance() {  
       return LazyHolder.single;  
    }  

使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的,同时又避免了同步锁带来的性能影响。

标签:Singleton,23,private,single,static,单例,线程,设计模式
来源: https://blog.csdn.net/weixin_43063840/article/details/106267144

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有