单例模式(饿汉、懒汉)高频面试考点

单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例。
  • 3、单例类必须给所有其他对象提供这一实例。

饿汉模式(初始就直接创建好)

类加载的时候实例创建并初始化好了,所以是线程安全的。

//外界不能 new 这个类,所以用 static 来修饰字段和方法
//不允许在类外修改创建的实例,所以实例用 private 声明
public class Singleton {
    private Singleton(){}
    private static Singleton singleton=new Singleton();//直接创建好
    public static Singleton getInstance(){
        return singleton;
    }

懒汉模式(需要时再创建)双重检测保证线程安全

singleton = new Singleton();

该语句非原子操作,实际是三个步骤。

  • 1.给singleton分配内存;
  • 2.调用 Singleton 的构造函数来初始化成员变量;
  • 3.将给singleton对象指向分配的内存空间(此时singleton才不为null);

必须使用volatile保证执行顺序,比如三个步骤重排序后为1 3 2,这样第一个线程初始化对象到一半,第二个线程来发现已经不是null了就直接返回了 实际上该对象此时还没有完全初始化 可能会出现这个问题。

synchronized使用Singleton类的Class对象作为锁对象,当多个线程同时访问getInstance()方法时,只有一个线程能够进入同步代码块实例化Singleton类,保证了单例的唯一性。

public class Singleton {
    private Singleton(){}
    private static volatile Singleton singleton=null;
    public static Singleton getInstance(){
        if(singleton==null){//第一次判断是为了提升效率,先判断若不为null,锁也没必要抢,抢锁开销是很大的
            synchronized (Singleton.class){
                if(singleton==null){
                    singleton=new Singleton();
                }
            }
        }
        return singleton;
    }
}

全部评论

相关推荐

评论
3
7
分享

创作者周榜

更多
牛客网
牛客企业服务