单例模式(一)

Andy 2023年05月26日 559次浏览

单例模式需要注意的地方:

单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
参考菜鸟教程的设计模式单例模式

1、懒汉式,线程不安全

public class Singleton {  
	//私有静态此对象,那此对象如果存在只能存在一个,由静态来决定的
    private static Singleton instance;  
    //私有构造方法,不让调用者new
    private Singleton (){}  
  //单线程没问题,多线程不行,因为有可能在前一个还没创建的时候另一个线程也进去了
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

2、懒汉式,线程安全

public class Singleton {  
//私有静态对象
    private static Singleton instance;  
    //私有构造函数
    private Singleton (){}  
    //加了一个synchronized 独占锁,防止上面的情况发生 ,更像悲观锁
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

3、饿汉式,线程安全

public class Singleton {  
//自己new出来了此对象,并且是静态的,那只能存在一个此对象
    private static Singleton instance = new Singleton();  
    //私有构造方法
    private Singleton (){}  
    //谁用此对象就返回已经创建好的静态的此对象
    public static Singleton getInstance() {  
    return instance;  
    }  
}

4、双检锁/双重校验锁,线程安全

public class Singleton {  
  //公共可见此静态对象,用了关字volatile 
    private volatile static Singleton singleton;  
    //私有化构造方法
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
   // synchronized(类的名.class)是全局锁,不管有几个对象就公用一把锁,更像乐观锁
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

5、登记式/静态内部类,线程安全

public class Singleton {  
//内部静态类
    private static class SingletonHolder {  
    //静态最终不可变的INSTANCE,实例化父对象 
    private static final Singleton INSTANCE = new Singleton();  
    }  
    //私有构造方法
    private Singleton (){}  
    //final,该方法被锁定,可以防止任何继承类修改它的意义和实现;
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

这个实现懒加载的方式是有Singleton 不一定有此对象的实例化,当调用getInstance才实例化内部类,在调用内部类创建父类的实例对象(这个内部类只能由Singleton 调用,外部是不能调用的),还是不可变的,说明实例化一次后,以后调用的都是第一次实例化的

6、枚举,线程安全

//简单但是不好理解
//描述::这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

菜鸟上的评价:
一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

自己的感觉:感觉第4种双检锁挺好理解的,而且性能又这么好,为什么不一开始就直接用双检锁机制呢,还能忽略一些细节,因为它都满足了
————————————————
版权声明:本文为CSDN博主「胖墩的IT」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43113679/article/details/99291545