面试笔记之手写单例模式

1. 前言

今天面试前,笔试中遇到写单例模式的试题,之前也参考一些优秀博主的博客写过一遍。
在此,再次整理一下。

2. 单例模式要点

实现单例模式有以下三个要点:
1)首先要确保全局只有一个类的实例:要保证这一点,至少类的构造器要私有化
2)单例的类只有自己创建自己:因为构造器私有了,但还要有一个实例,只能自己创建咯
3)单例类必须能够提供自己的唯一的实例给其他类:就要有一个公共的方法能返回该实例类的唯一实例

3. 单例类的实现

单例类的实现有以下6种(两种饿汉式,两种懒汉式,双重校验锁及静态内部类):

具体介绍及实现如下:

1)饿汉式——静态常量方式(线程安全)
该方式在类加载时就初始化,天然线程安全
实现代码如下(注意使用了static):

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getSingleton () {
        return instance;
    }
}

2)饿汉式——静态代码块方式(线程安全)

public class Singleton {
    private static Singleton instance;
    static {
        instance = new Singleton();
    }
    private Singleton() {}
    public static Singleton getSingleton () {
        return instance;
    }
}

3)懒汉式(线程不安全)
第一次调用才初始化,实现了懒加载特性,多线程禁用

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static Singleton getSingleton() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4)懒汉式(线程安全)
方法加上同步锁,相较于3性能会有折损,但也还好

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized Singleton getSingleton() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

5)双重校验锁(线程安全,效率高)
注意volatile的使用,保证了各线程对singleton静态实例域修改的可见性

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getSingleton() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

6)静态内部类实现单例(线程安全,效率高)
这种情况下Singleton被装载了,instance不一定被初始化。
因为SingleHolder类没有被主动使用,只有通过显示调用getInstance方法时,才会显式装载SingleHolder类,从而实例化instance。
注意内部类SingleHolder要用static修饰,且其中静态变量INSTANCE必须是final的

public class Singleton {
    private static class SingleHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton() {}
    public static Singleton getSingleton() {
        return SingleHolder.INSTANCE;
    }
}

参考链接:https://www.cnblogs.com/happyone/p/11221157.html

步履不停
原文地址:https://www.cnblogs.com/yuanyunjing/p/15426191.html