面试之手写单例模式总结:懒汉式,饿汉式,双重校验

一.单例模式介绍


单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

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


单例模式要点
  1. 单例类只能有一个实例------------>类构造器私有化
  2. 单例类必须自己创建自己的实例------------>类内部创建实例对象
  3. 单例类必须给所有其他对象提供这一实例------------>一个公共的方法能返回该单例类的唯一实例

二.代码:


1.懒汉式:
//线程不安全
class Singleton {
    
    private static Singleton singleton = null;//唯一实例
    private Singleton(){}//构造方法
    public static Singleton getInstance() {//get方法
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

懒汉模式:只有到使用时才初始化类的实例对象。


2.懒汉式(线程安全版):
//线程安全
class Singleton {
    
    private static Singleton singleton = null;//唯一实例
    private Singleton(){}//构造方法
    public static synchronized Singleton getInstance() {//get方法
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

通过synchronized修饰get方法,保证多线程的线程安全。


3.饿汉式(静态常量):
class Singleton {

    private static Singleton singleton = new Singleton();
    
    private Singleton(){}//构造方法

    public static  Singleton getInstance() {//get方法
        return singleton;
    }
}

饿汉模式:类加载的时候就初始化对象实例。这样可保证多线程下的线程安全


4.饿汉式(静态代码块):
class Singleton {

    private static Singleton singleton;

    private Singleton(){}//构造方法
    
    static {
        singleton = new Singleton();
    }

    public static  Singleton getInstance() {//get方法
        return singleton;
    }
}

静态代码块在类加载时会提前执行,所以也能保证在使用时该实例是唯一的。并且线程安全。

5.双重校验锁:
class Singleton {

    private static volatile Singleton singleton;

    private Singleton(){}//构造方法

    public static  Singleton getInstance() {//get方法
    
        if (singleton == null) {//第一次校验
            synchronized (Singleton.class){
                if(singleton==null){//第二次校验
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

双重校验可以减少锁获取和等待的时间,synchronized关键字保证线程安全。

注意:禁止指令重排优化这条语义直到jdk1.5以后才能正确工作。此前的JDK中即使将变量声明为volatile也无法完全避免重排序所导致的问题。所以,在jdk1.5版本前,双重检查锁形式的单例模式是无法保证线程安全的。


6.静态内部类:
class Singleton {

    private static class Holder {
        private static Singleton singleton = new Singleton();
    }
     
    private Singleton(){}
         
    public static Singleton getSingleton(){
        return Holder.singleton;
    }
}

静态内部类的加载不需要依附外部类,在使用时才加载,不过在加载静态内部类的过程中也会加载外部类,这样就实现了需要延时加载的需求。

你可能感兴趣的:(Java设计模式,单例模式,懒汉,饿汉)