单例模式

单例模式

第一种实现

/**
 * 懒汉模式
 * 单利的实例在第一次使用的时候创建
 * 线程不安全
 * 
 */
public class Singleton1 {
    //私有构造函数
    private Singleton1(){

    }
    //单例对象
    private static Singleton1 instance = null;

    //静态的工厂方法
    public static Singleton1 getInstance(){
        if(instance == null){
            instance = new Singleton1();
        }
        return instance;
    }
}

 第二种实现

/**
 * 饿汉模式
 * 单利的实例在类装载的时候创建
 * 线程安全
 * 不足:如果构造函数处理过多类加载会变慢。如果实例不适用会造成资源浪费
 *
 */
public class Singleton2 {
    //私有构造函数
    private Singleton2(){

    }
    //单例对象
    private static Singleton2 instance = new Singleton2();

    //静态的工厂方法
    public static Singleton2 getInstance(){
        return instance;
    }
}

 第三种实现

/**
 * 懒汉模式
 * 单利的实例在第一次使用的时候创建
 * 线程安全,不推荐,性能差
 *
 */
public class Singleton3 {
    //私有构造函数
    private Singleton3(){

    }
    //单例对象
    private static Singleton3 instance = null;

    //静态的工厂方法
    public static synchronized Singleton3 getInstance(){
        if(instance == null){
            instance = new Singleton3();
        }
        return instance;
    }
}

  第四种实现

/**
 * 懒汉模式  -->双重同步锁单例模式
 * 单利的实例在第一次使用的时候创建
 * 线程不安全
 */
public class Singleton4 {
    //私有构造函数
    private Singleton4() {

    }

    //instance = new Singleton4(); 的三步骤
    //1、分配内存对象空间, 2、初始化对象,3、设置instance指向刚分配的内存

    //单线程没问题,多线程JVM和CPU优化,会发生指令重排
    //1、分配内存对象空间,2、设置instance指向刚分配的内存,3、初始化对象
    
    //问题描述,两个线程,在发生指令重拍的情况时,线程A执行到instance = new Singleton4()的第2步,线程B执行到【if (instance == null) {//双重检测机制】 这时候instance有值,
    //线程B直接返回了,但这时候instance还没有初始化,线程B的调用程序使用到instance会出错

    //单例对象
    private static Singleton4 instance = null;

    //静态的工厂方法
    public static Singleton4 getInstance() {
        if (instance == null) {//双重检测机制
            synchronized (Singleton4.class) {//同步锁
                if (instance == null) {
                    instance = new Singleton4();
                }
            }
        }

        return instance;
    }
}

  第五种实现

/**
 * 懒汉模式  -->双重同步锁单例模式
 * 单利的实例在第一次使用的时候创建
 * 线程安全
 */
public class Singleton5 {
    //私有构造函数
    private Singleton5() {

    }

    //instance = new Singleton4(); 的三步骤
    //1、分配内存对象空间, 2、初始化对象,3、设置instance指向刚分配的内存

    //单线程没问题,多线程JVM和CPU优化,会发生指令重排,使用volatile可防止指令重排

    //单例对象 volatile + 双重检测机制 -->禁止指令重排
    private volatile static Singleton5 instance = null;

    //静态的工厂方法
    public static Singleton5 getInstance() {
        if (instance == null) {//双重检测机制
            synchronized (Singleton5.class) {//同步锁
                if (instance == null) {
                    instance = new Singleton5();
                }
            }
        }

        return instance;
    }
}

  第六种实现

 

/**
 * 饿汉模式
 * 单利的实例在类装载的时候创建
 * 线程安全
 * 不足:如果构造函数处理过多类加载会变慢。如果实例不适用会造成资源浪费
 */
public class Singleton6 {
    //私有构造函数
    private Singleton6() {

    }

    //步骤1必须要在步骤2前面,因为静态域和静态代码块是按照书写的顺序执行的,反过来instance会为空
    //步骤1
    //单例对象
    private static Singleton6 instance = null;

    //步骤2
    static {
        instance = new Singleton6();
    }



    //静态的工厂方法
    public static Singleton6 getInstance() {
        return instance;
    }
}

  第七种实现

/**
 * 枚举模式, 最安全
 * 线程安全
 * 推荐
 */
public class Singleton7 {
    //私有构造函数
    private Singleton7() {

    }

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

    private enum Singleton {
        INSTANCE;
        private Singleton7 singleton;

        //JVM保证这个方法绝对只调用一次
        Singleton() {
            singleton = new Singleton7();
        }

        public Singleton7 getInstance() {
            return singleton;
        }
    }
}

 

posted @ 2022-08-19 15:09  ALittleYuan  阅读(41)  评论(0)    收藏  举报