单例模式的实现方式和推荐实现方式

一、实现单例模式的两个要素

1)私有的构造函数

2)提供一个static修饰的getInstance方法

二、难点:

1)线程安全

2)避免资源浪费

3)避免反序列化破坏单例

三、实现

1、饿汉模式(线程不安全,不推荐使用)


public class SingletonExample1 {

    public static SingletonExample1 singleton = null;

    private SingletonExample1() {
    }

    public static SingletonExample1 getInstance() {
        if (Objects.isNull(singleton)) {
            singleton = new SingletonExample1();
        }
        return singleton;
    }

}

2、懒汉模式(线程安全,不推荐使用)

 /** 优点
 *  线程安全
 * 缺点:
 *  虽然是线程安全的,项目初始化时创建对象,如果初始化对象如果操作内容比较多,会拖慢项目启动速度
 *
 * @author
 */
ublic class SingletonExample2 {

    public static SingletonExample2 singleton = new SingletonExample2();

    private SingletonExample2() {
    }

    public static SingletonExample2 getInstance() {
        return singleton;
    }

}

3、双检锁模式

package com.sp.singleton;


import java.util.Objects;

/**
 * 懒汉模式-> 双检锁模式
 *
 * 优点
 *  线程安全
 * 缺点
 *  1、实现繁琐
 *
 * @author 
 */
public class SingletonExample3 {

    /**
     * 使用volatile关键字,避免出现指令重拍和保持 变量的可见性
     */
    public static volatile SingletonExample3 singleton = null;

    private SingletonExample3() {

    }

    public static SingletonExample3 getInstance() {
        //为空时创建
        if (Objects.isNull(singleton)) {
            synchronized (SingletonExample3.class) {
                //第二次判空,为避免另外一个线程获取锁之后,重新创建
                if (Objects.isNull(singleton)) {
                    singleton = new SingletonExample3();
                }
            }
        }
        return singleton;
    }

    /**
     * 解决被序列化和反序列化破坏的单例模式
     *
     * @return
     */
    private SingletonExample3 readObject() {
        return singleton;
    }

}

4、使用枚举创建单例(推荐使用)

package com.sp.singleton;

/**
 * 使用枚举创建单例模式
 *
 * 1、JVM 保证线程安全
 * 2、与懒汉模式相同用到时创建对象,避免资源浪费
 *
 * @author 
 */
public class SingletonExample4 {

    public static SingletonExample4 singleton = new SingletonExample4();

    private SingletonExample4() {

    }

    public static SingletonExample4 getInstance() {
        return SingletonEnum.SINGLETON.getInstance();
    }

    private enum  SingletonEnum {
        SINGLETON;

        private SingletonExample4 singleton;

        /**
         * JVM保证构造函数只调用一次
         */
        SingletonEnum () {
            singleton = new SingletonExample4();
        }

        private SingletonExample4 getInstance() {
            return singleton;
        }
    }

}

5、静态内部类实现单例(需理解classloader原理)

package com.sp.singleton;

/**
 * 静态内部类 实现 单例模式
 *
 * 这种方式利用了classloader保证初始化对象时只要一个线程,与饿汉模式相比虽然虽然SingletonExample5被初始化了,
 * SingletonHolder没有被用到也不会初始化对象,来保证懒加载
 *
 * @author
 */
public class SingletonExample5 {

    private static class SingletonHolder {
        private static final SingletonExample5 singleton = new SingletonExample5();
    }

    private SingletonExample5() {

    }

    public static SingletonExample5 getInstance() {
        return SingletonHolder.singleton;
    }

}

猜你喜欢

转载自blog.csdn.net/luoyeyeyu/article/details/86422740
今日推荐