您的位置:首页 > 编程语言 > Java开发

java设计模式之单例模式

2015-12-02 19:02 453 查看
在java中,单例模式(Singleton)保证了在一个jvm中只有一个实例存在。

为什么使用单例模式?

1.对于一些需要频繁创建的大型对象,可以减小开销。

2.减少new的操作,减少了内存的访问频率。

3.有些逻辑需值需要一个实例存在。

一个简单的单例模式

public class Singleton {

private static Singleton singletonInstance = null;

private Singleton(){

}

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

return singletonInstance;
}

}

分析:

该单例在多线程环境下是会出问题的。

改进一:在getInstance方法上加synchronized关键字

public static synchronized Singleton getInstance()
{
if(singletonInstance == null)
singletonInstance = new Singleton();

return singletonInstance;
}

分析:

这样在每次获取实例的时候都需要加锁,性能明显下降,实际上只需要在第一次创建实例的时候需要加锁,之后再获取实例就不需要再加锁了。

改进二:只在创建实例的时候加锁

public class Singleton {

private static Singleton singletonInstance = null;

private Singleton(){

}

public static  Singleton getInstance()
{
if(singletonInstance == null){

synchronized(singletonInstance){

if(singletonInstance == null){

singletonInstance = new Singleton();
}
}
}
return singletonInstance;
}

}

分析:

这样还是会出现问题,主要是由于singletonInstance = new Singleton();这句话在jvm中执行的顺序造成的,如果jvm首先分配空间,然后赋给singletonInstance,最后初始化实例, 就会出现问题,如A、B两个线程,A、B同时进入if语句,A判断singletonInstance为空,执行new操作,jvm分配了一块空间并赋给singletonInstance,但并没有初始化,然后A离开synchronized块,B进入发现singletonInstance不为空,直接返回,但实际上此时并未初始化,在使用的时候就会出现问题。

改进三:使用内部类

public class Singleton {

private Singleton(){

}

private static class SingletonFactory
{
private static Singleton singletonInstance = new Singleton();
}

public Singleton getInstance()
{
return SingletonFactory.singletonInstance;
}

}

分析:

JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕,这样我们就不用担心上面的问题。同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题。实际上如果实例化抛出异常的话也会出问题。

另一种相对完美的实现:创建和获取实例分离

public class Singleton {

private static Singleton singletonInstance = null;

private Singleton(){

}

private static synchronized void init()
{
singletonInstance= new Singleton();
}

public static  Singleton getInstance()
{
if(singletonInstance == null){
init();
}
return singletonInstance;
}

}

总结:实际上没有完美的方式,只不过根据自己的情况选择合适的方式罢了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java