单例模式的几个方法

单例模式

什么是单例模式

单例模式就是只允许有一个实例存在,自己向外部提供方法获取实例。

一般获取对象都是通过new对象来完成,这样系统中肯定就不至一个实例。我们怎么来完成这种单例模式了,我们可以通过把构造方法给私有化,这样外部就无法直接通过new来获取这个对象,我们内部再提供一个 getInstance() 来获取对象。

单例模式的应用场景

  1. 需要生成唯一序列的环境。
  2. 要频繁实例化然后销毁的对象。
  3. 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  4. 方便资源相互通信的环境。

单例模式的实现

下面就用Person类来完成代码实现

  1. 第一种,在类加载的时候就完成对象的实例化
public class Person1 {

    private static Person1 person = new Person1();

    private Person1(){};

    public static Person1 getInstance() {
        return person;
    }
}

优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

  1. 第二种,第一种的升级,在getInstance()再生成实例
public class Person2 {

    private static Person2  person = null;

    private Person2(){};

    public static Person2 getInstance() {
        if (person == null) person = new Person2();
        return person;
    }
}

这种方式在多线程的情况下会创建多个实例,所以有了第三种方式。

  1. 第三种,双检
public class Person3 {

    private static Person3 person = null;

    private Person3(){};

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

为什么需要两次检查,为什么一次不行了。

分别介绍两次检查的作用:

  • 第一次是为了效率,假如有两个线程A和B,如果没有第一次检查,A得到锁,B来了但是得不到锁,那B就等待,等待A释放这个锁,当B的到锁后再去判断。那么其实B等待的这个时间是不必要的,因为A已经把实例构建好了,B一直等待A释放锁,然后得到锁后发现实例也创建好了。
  • 第二次是为了单例,还是以A和B两个线程来说,如果没有第二次检查,A得到锁,B来了但是得不到锁,那B就等待,等待A释放这个锁。这里和第一次很像,但是这次没有第二次检查,B得到锁后并不知道A已经创建好了实例,那么B会自己再创建一个实例,这样就不是单例模式了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值