创建单例Singleton的三种方式:懒汉式、饿汉式、枚举类

一、什么是单例
Singleton是指只实例化一次的类,系统中只存在一个该类的实例,就好像一个国家只能同时存在一个总统,多了得乱啊。比如说美国总统这个类在上一个运行期实例化出了巴马总统。而在下一个运行期又重新实例化出一个特朗普总统。

二、创建单例的三种方式
(1)懒汉式单例,顾名思义,这个单例比较懒,我不来调用getInstance()方法,它就不会进行实例化。

懒汉式单例1.0

public class Singleton
{
    // 懒汉式单例,不马上实例化而是等到调用getInstance方法再进行实例化
    private static Singleton singleton = null;

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

        return singleton;
    }
    //构造器必须私有,防止进行多次实例化
    private Singleton()
    {

    }
}

在懒汉式1.0中呢存在一个问题,那就是线程安全,如果有并发环境下有多个线程同时进行if(singleton==null)检查,然后同时检查通过并创建出多个对象,那么就不是单例了,就好像美国佬同时选出了几个总统,这不得乱了套。我们得对选总统这件事控制一下,确保一个任期内只能选出一位总统。

懒汉式单例2.0

public class Singleton
{
    // 懒汉式单例,不马上实例化而是等到调用getInstance方法再进行实例化
    private static Singleton singleton = null;

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

            }
        }

        return singleton;
    }

    private Singleton()
    {

    }
}

现在呢我们把singleton=new Singleton(),这个代码块给锁起来了,那是不是很安全了呢,看起来好像是哈,现在不能同时产生总统了,但是呢!稍微有点多线程基础的兄弟都知道,我们有个很重要的没同步啊!那就是if(singleton==null),假如多个线程同时通过这个判断,然后基于一个对象的锁只能同时被一个线程拥有,现在呢singleton=new Singleton()由原来多个对象并行变成串行了。嘿嘿嘿,按照基本法我们现在不同时选出总统了,但是我们可以排着队来,你选了该我们选。最终还是会选出多个总统,还是乱套。看到这里,解决方案已经很明显了!

懒汉式单例3.0


    private static Singleton singleton = null;

    public static Singleton getInstance()
    {

        synchronized (Singleton.class)
        {
            if (singleton == null)
            {
                singleton = new Singleton();

            }
        }

        return singleton;
    }

这次确实可以了,但是呢每次进入getInstance方法都要同步,是很极端的行为,是会影响性能的。

懒汉式4.0

    public static Singleton getInstance()
    {

        if (singleton == null)
        {

            synchronized (Singleton.class)
            {
                if (singleton == null)
                {
                    singleton = new Singleton();

                }
            }
        }

        return singleton;
    }

现在呢加入了一个双重检查!这样防止了每次进入都必须同步,又保证了只产生一个实例对象!

(2)饿汉式单例
饿汉式单例:我很饿,我进来就要吃东西,东西必须提前准备好!哈哈,这可能就是为什么叫饿汉式的原因吧,瞎掰的!饿汉式单例指加载类时就实例化该类的对象,而不是等到调用getInstance方法再去实例化,因为单例的实例被声明成 static 和 final 变量了,在第一次加载类到内存中时就会初始化,所以创建实例本身是线程安全的。

public class Singleton
{
    // 饿汉式单例,马上实例化而不是等到调用getInstance方法再进行实例化
    private static final Singleton singleton = new Singleton();

    public static Singleton getInstance()
    {
        return singleton;
    }

    private Singleton()
    {

    }
}

(3)枚举类创建单例
这也是Effective Java中推荐的方法,这种方法更加简洁,无偿提供了序列化机制,线程安全,绝对防止多次实例化,已经成为实现Singleton的最佳方法。

public enum Singleton
{
   SINGLETON;
}

直接通过Singleton.SINGLETON进行访问。

三、结语
哈哈,本人也是16年应届生,记得前面做华为笔试题遇到过,当时可耻的在构造器中写了返回单例,哈哈,后面还舔着脸问是不是错得很离谱,无奈面试官叫我回来百度!最近看Effective Java结合网上经典讲解理解了一番。顺便记录下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值