单例模式的几种写法

来源:互联网 发布:淘宝高仿包包批发 编辑:程序博客网 时间:2024/05/08 20:49

    • 测试类
    • 单例模式
      • 饿汉模式
      • 懒汉模式对整个方法加锁
      • 懒汉模式对关键语句加锁
      • 静态内部类实现懒汉模式
      • 枚举形式的单例简单安全


测试类

/** * @author mnmlist@163.com * @date 2017/05/21 * @time 12:04 */public class SingletonDemo {    public static void main(String[] args) {        // test Singleton1        System.out.println(Singleton1.getInstance());        System.out.println(Singleton2.getInstance());        System.out.println(Singleton3.getInstance());        System.out.println(Singleton4.getInstance());        System.out.println(Singleton5.INSTANCE);    }}

单例模式

1. 饿汉模式

/** * 饿汉模式 * 优点:书写简单,JVM本身保证一个类在一个ClassLoader中只会被初始化一次 * 缺点:a.加载就初始化;b.这种创建方法并不灵活,例如实例是依赖参数或者配置文件的 */class Singleton1 { private static final Singleton1 singleton1 = new Singleton1(); private Singleton1() {} public static Singleton1 getInstance() {   return singleton1; }}

2. 懒汉模式,对整个方法加锁

/** * 优点:简单 * 缺点:效率低,对整个方法进行加锁,而真实的情况是只有singleton实例为null的时候才需要对方法加锁 */class Singleton2 {    private static Singleton2 singleton2;    private Singleton2() {}    //直接对整个方法加锁,但多数情况下是null != singleton2的,也就是执行到null == singleton2判断就return的    //所以对整个方法进行加锁效率太低    public static synchronized Singleton2 getInstance() {        if (null == singleton2) {            singleton2 = new Singleton2();        }        return singleton2;    }}

3. 懒汉模式,对关键语句加锁

/** * 优点:看起来挺有技术含量 * 缺点:其实太复杂,不够简洁 */class Singleton3 {    private volatile static Singleton3 singleton3;  //volatile 禁止singleton3 = new Singleton3();指令重排    private Singleton3() {}    public static synchronized Singleton3 getInstance() {        //先判断singleton3是否为null,对象已经存在的话就不用再同步了,提升效率        if (null == singleton3) {            synchronized (Singleton3.class) {                //加锁的过程中可能singleton3已经被赋值,所以还需要再判断下,防止出错                if (null == singleton3) {                    /**                     * 该操作并不是一个原子操作,它其实包括3个步骤,                     *  1. 给 singleton 分配内存                     *  2. 调用 Singleton 的构造函数来初始化成员变量,形成实例                     *  3. 将singleton对象指向分配的内存空间                     * 在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和                     * 第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2,                     * 所以把singleton声明成 volatile,防止指令因指令重排导致问题                     */                    singleton3 = new Singleton3();                }            }        }        return singleton3;    }}

4. 静态内部类实现懒汉模式

/** * 静态内部类实现,简单且不需要额外的同步 */class Singleton4 {    public Singleton4() {    }    /**     * getInstance()方法被调用的时候才会初始化实例     */    public static Singleton4 getInstance() {        return SingletonHolder.INSTANCE;    }    private static class SingletonHolder {        public static Singleton4 INSTANCE = new Singleton4();    }}

5. 枚举形式的单例,简单安全

/** * 保证单例且线程安全 */enum Singleton5 {    INSTANCE;}
原创粉丝点击