结论先行

Lazy
初始化
多线程
安全
优点 缺点
饿汉式 没有加锁,执行效率会提高 类加载时就初始化,浪费内存
懒汉式 第一次调用才初始化,避免内存浪费 必须加锁 synchronized 才能保证单例,但加锁会影响效率
双重校验锁
的懒汉式
安全且在多线程情况下能保持高性能 getInstance() 的性能对应用程序很关键
静态内部类 -达到 lazy loading 效果
-只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance
可以被反射破坏
枚举类 -支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化
-不能被反射破坏

实现代码:

饿汉式

/**
 * 饿汉式实现单例模式
 */
public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式

/**
 * 懒汉式单例模式(线程安全)
 */
public class Singleton {

    private static Singleton instance;

    private Singleton() {
    }

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

双重校验锁的懒汉式

/**
 * 懒汉式单例模式(同步代码块双重检查) 此处注意引用需要用volatile修饰,防止指令重排序
 */
public class Singleton {

    private Singleton() {
    }

    private static volatile Singleton instance;

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

静态内部类

/**
 * 静态内部类实现单例模式
 */
public class Singleton {

    private Singleton() {
    }

    private static class SingletonHolder  {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder .INSTANCE;
    }
}

枚举类

/**
 * 枚举实现单例模式
 */
public enum Singleton {
    INSTANCE;

    public void whateverMethod() {
        //方法体
    }
}


//想要使用时
public static void main(String[] args){
    Singleton.INSTANCE.whateverMethod();
}

关于单例模式

用来创建独一无二的,只有一个实例对象,是一种最简单的设计模式。

特点:

  • 一个类只能有一个实例
  • 自己创建这个实例
  • 整个系统都要使用这个实例

对于有一些对象,其实例我们只需要一个,比方说:线程池、缓存(cache)、日志对象等,如果创建多个实例,就会导致许多问题产生,比如资源使用过量、程序行为不可控,或者导致不一致的结果。

本文部分参考