单例模式的六种实现和简单介绍

    在实际开发中,我们常会需要使用到单例模式。单例模式的核心就是,一个类只有一个实例。

    如何实现只有一个实例呢?关键是:构造函数的私有化。

    单例模式的实现有很多中,这里介绍一下常见的六种。

    和其他介绍单例的不一样。我们首先介绍一种不常用的,但是我认为很有潜力,以后的单例实现最常用的方式。那就是使用枚举来实现单例模式。然后才是其他几种实现。上代码:

    (1)枚举实现单例:

public enum Singleton {
    INSTANCE;
    public void showMessage(){
        System.out.println("枚举");
    }
}

        是不是超简单?超级清晰?使用的时候直接Singleton.INSTANCE。就可以了。

        因为这种方式在JDK1.5之后才支持,所以在一些老系统上可能不能用。但是现在JDK10都出来了,所以我认为以后这种方式会最常用。为什么:1.很简洁,甚至简单。2.自动支持序列化机制。3.绝对防止被多次实例化。4.线程安全。

        Perfect!

        (2)懒汉式线程不安全:

public class Singleton {
    private static Singleton instance;

    private Singleton(){}

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

        很简单的一种单例模式,(当然,枚举更简单)很容里理解:静态私有的实体类,私有的构造方法,提供get方法,只需要在第一次调用的时候实例化一次。

        但是缺点也很明显,线程不安全。多线程的情况下就不能正常工作了。

        (3)懒汉式线程安全:

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

        和第二种方式的唯一区别就是:在get方法加了锁synchronized。这样就线程安全了。但是缺点也很明显,使用锁之后性能降低了。

        (4)饿汉式:

public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}

        饿汉式基于classloder的机制实现了线程安全。但是在类装载的时候就加载了实例,浪费内存,也不满足lazy loading的效果。

        饿汉式和懒汉式可以见名知义地理解为:懒汉,他很懒,你不去找他他就不给你实例化。饿汉就是饿慌了,你不去找他他都给你实例化好了。

        (5)双重校验锁:

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

        采用双锁机制实现单例,多线程下也保证安全和高效。但是呢,缺点也很明显:很复杂。至少对我来说,双重校验锁什么的根本不明白啊。照着写还行,要我解释就···弄不懂了。

        (6)静态内部类:

public class Singleton {
    private static class SingletonHolder{
        private static final Singleton instance = new Singleton();
    }
    private Singleton(){}
    public static final Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

        和双重校验锁一样的效果,但是简单一些。也是用classloder的机制实现线程安全。且类加载的时候不一定实例化单例。

        总结:通常情况下,饿汉式的单例已经能满足日常使用了。有特殊需要的时候可以考虑双重校验锁。有反序列化创建爱你对象的需求的时候使用枚举。不过了,就个人而言,我更喜欢枚举的方式。正如前面所说:1.简洁。2.支持序列化。3.绝对单例。4.线程安全。Perfect!

        差不多就是这样,希望大家能找到自己喜欢、工作适用的单例模式。

        

        最后呢,作者水平有限,有什么问题大家可以提出来共同探讨学习。

        差不多就是这样,祝大家学习愉快。谢谢。

                                                                      —— by:轩辚 ——





    

        
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值