单例设计模式(Java)

单例模式

即表示内存中只有一个该类的实例,可以节约内存、提高性能。
常见的做法有两种:懒汉式和饿汉式。

饿汉式

这里的“饿汉”是说,不管调用端代码是否最终需要一个本例的实例,都先在内存中创建好。

代码

public class Singleton {
    private static Singleton singleton = new Singleton();
    public static Singleton getNewInstance() {
        return singleton;
    }
}

分析

饿汉式逻辑简单,线程安全,但是存在性能改良的空间,因为如果静态方法从来没有被调用过,在内存中new出一个对象完全没有必要。

懒汉式

与饿汉式相对应,懒汉式的“懒”体现在只有调用了静态方法才创建实例,如果从来没有调用过,就不创建实例。

代码

public class Singleton {
    private static Singleton singleton;
    public static Singleton getNewInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

分析:这种做法保证内存中只有一个该类的实例,也做到了只有真正调用了才开辟内存创建对象,但是线程不安全。
如果有不止一个线程在调用此方法,A刚判断实例为空,进去new对象了,但是还没new完并赋值给singleton的时候,B也进来,此时singleton还是null,所以也进来new了一个对象,所以就会出现new了两个对象,出现了线程不安全的问题。
可以做如下改良:

public class Singleton {
    private static Singleton singleton;
    //给方法加同步
    public static synchronized Singleton getNewInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

给方法加上同步之后就能保证线程安全了,但是每次调用方法的时候,都需要进行同步判断,性能太差。
然后就可做如下改良:

public class Singleton {
    private static Singleton singleton;
    public static Singleton getNewInstance() {
        if (singleton == null) {
            //语句块同步
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

这样应该没什么问题了,但是细细分析来看,线程还是不同步的。
比如:A线程判断为null后进来了,并进入同步块new对象,此时B线程进来了判断还是null,照样进入了if块,因为同步,所以只能在外边等着,当A线程走出同步块,B线程进入,也new了个对象,也导致了线程不安全的问题。基于以上分析,可以得到思路,在同步块里再判断一次ok了!
终极版本:

public class Singleton {
    private static Singleton singleton;
    public static Singleton getNewInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                //再次判断,即使另一个线程进来了,也不会做任何事情。
                if(singleton==null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

分析:这样就可以保证即时另一个线程顺利进入了外层if块,但是当前一个线程走出同步块的时候,singleton已经非空了,第二个线程进入了同步块,也不会做任何事情就会退出,最终return的还是唯一的一个实例。这应该就是懒汉式的最终版本了。

最终比较

这两种设计方法都可以实现单例模式,饿汉式简单,如果对内存要求不是很严格可以采用,懒汉虽然更加复杂,但是更加高效,应该尽量使用此方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值