查看原文
其他

单例模式的 8 种写法,非常全!

栈长 Java技术栈 2020-10-08

概念

单例模式即一个 JVM 内存中只存在一个类的对象实例。

分类

1、饿汉式

类加载的时候就创建实例

2、懒汉式

使用的时候才创建实例

当然还有其他的生成单例的方式,双重校验锁,枚举和静态内部类,文中会有介绍。

懒汉式

1) 示例1

public class Singleton {  

    private static Singleton instance;  

    private Singleton (){}  

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

}

线程不安全,不可用。

2) 示例2

public class Singleton {  

    private static Singleton instance;  

    private Singleton (){}  

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

}

同步方法,线程安全,效率低,不推荐。

3) 示例3

public class Singleton {

    private static Singleton singleton;

    private Singleton() {}

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

}

线程不安全,会产生多个实例,不可用。

饿汉式

无线程安全问题,不能延迟加载,影响系统性能。

4) 示例1

public class Singleton {  

    private static Singleton instance = new Singleton();  

    private Singleton (){}  

    public static Singleton getInstance() {  
        return instance;  
    }  

}

5) 示例2

public class Singleton {  

    private static Singleton instance = null;  

    static {  
        instance = new Singleton();  
    }  

    private Singleton (){}  

    public static Singleton getInstance() {  
        return instance;  
    }  

}

6) 双重校验锁

public class Singleton {

    private static volatile Singleton singleton;

    private Singleton() {}

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

        }
        return singleton;
    }

}

双重校验锁,线程安全,推荐使用。

7) 静态内部类

public class Singleton {  

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

    private Singleton (){}  

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

}

静态内部类,线程安全,主动调用时才实例化,延迟加载效率高,推荐使用。

8) 枚举

public enum Singleton {  

    INSTANCE;  

    public void whateverMethod() {  

    }  

}

注意事项

1、考虑多线程问题

2、单例类构造方法要设置为private类型禁止外界new创建

private Singleton() {}

3、如果类可序列化,考虑反序列化生成多个实例问题,解决方案如下

private Object readResolve() throws ObjectStreamException {

    // instead of the object we're on, return the class variable INSTANCE  

    return INSTANCE;  

}

枚举类型,无线程安全问题,避免反序列华创建新的实例,很少使用。

使用场景

1、工具类对象

2、系统中只能存在一个实例的类

3、创建频繁或又耗时耗资源且又经常用到的对象

下面是单例模式在JDK的应用

另外,Spring 容器中的实例默认是单例饿汉式类型的,即容器启动时就实例化 bean 到容器中,当然也可以设置懒汉式 defalut-lazy-init="true" 为延迟实例化,用到时再实例化。

END


学习资料:

分享一份最新 Java 架构师学习资料

最近热文:

1、重磅:Java 14 正式发布了!
2、HTTP连接选HttpClient还是OkHttp?
3、运算神器 BigDecimal,了解一下?
4、从 0 编写自己的第一款 IDEA 插件!
5、一次 Druid 连接池泄露引发的血案!
6、每个程序员都必须掌握的 8 种数据结构!
7、如何在 Gihub 快速搜索开源项目?
8、怎么用追 MM 来理解 23 种设计模式?
9、我去,同事居然用明文存储密码!!!
10、以淘宝为例,解析大型电商服务端架构!
公众号干货实在太多,扫码关注Java技术栈公众号阅读更多。

点击「阅读原文」带你飞~

Modified on

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存