单例模式

一直以为单例模式是最简单的设计模式,感觉上是随手都可以写出来的,可是才读了设计模式的书籍,发现这个模式中也是有一些东西值得琢磨的,尤其是多线程牵扯进来的时候。

下面是我脑海中比较普遍的单例实现:


public class Singleton {

private static Singleton singleton;

private Singleton() {

}

public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton(); //延迟初始化
}
return singleton;
}

}


这段代码看起来是没有问题,但是在多线程中就可能导致singleton被多次赋值,最终导致单例失效。
为了解决这个问题有两种方法:
1、 急切初始化;
2、 同步。

先看看急切初始化,确实可以解决这个多线程的问题:


public class Singleton {
//JVM保证在加载这个类时先创建这个实例,保证了线程安全
private static Singleton singleton = new Singleton();

private Singleton() {

}

public static Singleton getInstance() {
return singleton;
}

}

如果应用总是创建并使用实例,或者在创建和运行方面的负担不太重,就可以使用这种急切创建实例的方法。

另外一种方法是,使用同步的方法synchronized:


public class Singleton {

private static Singleton singleton;

private Singleton() {

}

public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton(); //延迟初始化
}
return singleton;
}

}

以上代码保证了线程安全,但是如果此方法会被频繁调用,将会严重影响性能,因此这里有另外一种同步的方法,即利用双重检查加锁,首先检查实例是否已经创建了,如果还没有创建,才进行同步,只在第一次创建的时候同步:

public class Singleton {

private volatile static Singleton singleton;

private Singleton() {

}

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

}

如果我们关心性能,则以上方法可以大大降低getInstance的消耗。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值