单例设计模式

355 阅读4分钟

​每天一个面试题,有手就能学废,大家好,我是爱码士赵Sir!

1、什么是单例模式

单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点

就是这个类只能有一个对象,不能乱搞,然后通过一个方法能拿到它。

2、应用场景

全局管理类自己封装的SharedPreferencesManager,比如Okhttp中的okhttpclient也最好要保证全局单例,免得多次初始化浪费资源与性能,还有腾讯的bugly里面的CrashReport,CrashModule,还比如Fresco初始化 JavaWeb数据库的连接池

3、实现步骤

1、构造方法私有化,私有化了之后,外部就不会通过new的方式来产生它的实例了,

2、声明一个本类对象,自己要生成一个对象,让别人去用

3、给外部提供一个静态方法获取对象实例,静态的方法可以不用实例化对象就可以调用,直接用类名 直接去调用

4、实现的方式

1、饿汉式:对象的生命周期比较长,在声明本类对象的时候,直接new 一个实例,占用内存时间长,提高效率

//饿汉式 在类被加载后,对象被创建到程序结束后释放
class Singleton{  
    //构造方法私有化  
    private Singleton(){} 
     //声明一个本类的对象  
     private static Singleton  singleton=new Singleton();
     //提供一个静态方法获取对象实例  
     public static Singleton getInsatance(){  
         return singleton; 
     }
    
}

2、懒汉式 对象的生命周期比较短,在第一次调用getInstance方法时才会new一个对象供外部调用,占用内存时间短,第一次使用时,效率稍低点

建议大家用懒汉式,懒加载延迟加载

//懒汉式第一次调用getInstance方法时
class Singleton{  
    //构造方法私有化  
    private Singleton(){}  
    //声明一个本类的对象  
    private static Singleton  singleton;  
    //提供一个静态方法获取对象实例  
    public static Singleton getInsatance(){
    if(singleton==null){
    singleton==new Singleton(); 
    }   
    return s;  
    }
}

上面的demo 在多线程访问的时候,会有安全问题,会有可能产生多个实例,多线程情况下的单例,怎么实现呢?大佬们在评论区留言!

更新!等了好多天也没见你们留言!只能我来更新一下!=========

饿汉式的单例模式,肯定是线程安全的咱们主要来看懒汉式的单例模式怎么才能保证线程安全

  • 先来看第一种方法
public class Singleton {
    private static Singleton singleton=null;
    private Singleton(){

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

}

我们采用线程同步块的方法给这个getInstance加一个锁,这种方法虽然保证了线程安全,但是每一次调用的时候都会执行getInstance方法,每一次都去拿锁,执行方法的开销会增大,咱们能不能只是在创建的时候加锁呢!就是说我们不需要在每次调用的时候线程去竞争,只需要在new 操作的时候线程去竞争,所以第二版就来了

    //这种写法是不能保证线程安全的
   public  static  Singleton getInstance(){
        if(singleton==null){
            synchronized (Singleton.class){
                singleton=new Singleton();
            }
        }
        return  singleton;
    }

你只锁住了new 操作,但是还会产生多个对象的,因为很有可能多个线程同时获取的singleton==null,进到if里边然后多个线程进行排队去执行synchronized代码快里边的内容,还是会进行多次的new!所以我们需要再加一层判断!

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

这种写法才是既是线程安全的,又是最节省性能的写法!学废了么

5、单例的优点

1、在设计一些工具类的时候(通常工具类只有功能方法,没有属性)

2、工具类可能会被频繁调用

3、目的是为了节省重复创建对象所带来的内存消耗,从而提高效率

能不能使用构造方法私有化+静态方法来代替单例?

//使用构造方法私有化+静态方法 来实现工具类 比如JDK里的Math函数class Tools{ priavte Tools(){ } public static void print(){ }} 这种实现方式,所有的方法都是静态的,方法里的临时变量都会存在方法区而单例模式的方法依赖于对象,可以不是静态的,执行方法的时候会入栈然后创建临时变量,方法执行完毕会出栈临时变量会 销毁,这样比的话,单例模式的内存开销比构造方法私有化加静态方法实现要小

你学废了么​!么么哒么么哒​么么么么哒!