您的位置:首页 > 其它

单例模式

2016-05-05 12:12 246 查看
在Java设计模式中,单例模式无疑是使用特别频繁的一种,本文就介绍一下单利模式的常用形式

单例模式主要分为饿汉式和懒汉式,作用是保证这个类只会被实例化一个对象。饿汉式是在穿件对象引用的时候就实例化对象,懒汉式用于延迟加载,将会在需要使用此对象时实例化对象,懒汉式往往会带来一些安全性问题。下面就详细描述一下两种单利模式。

饿汉式单例模式(例):

public class SingleInstance{

//创建并实例化一个私有的静态对象,private保证不会被外界直接调用,static保证只会被创建一个对象
private static SingleInstance singleInstance = new SingleInstance();

//私有化构造器,作用是不让外界使用构造方法来实例化对象,而是只能通过SingleInstance提供的共有方法来获取
private SingletonInstance(){

}

//提供一个公有方法,外界通过此方法获取到这个类的对象
public static SingletonInstance getInstance(){
return singleInstance;
}

}


饿汉式比较简单,就不再赘述,重点看注释

懒汉式将从不安全到安全由浅入深讲解,先看最简单的写法:

public class SingleInstance{
private SingleInstance(){}

private static SingleInstance singleInstance;

public SingleInstnce getSingleIntance(){

singleInstance = new SingleInstance();
return singleInstance;
}
}
从代码中可以看到,外界如果调用了getInstance()方法就会去实例化一个singleInstance方法,这样不能满足只允许实例化一个对象的需求,所以我们加上一个判断,如果singleInstance对象为null就实例化,否则就直接返回,如以下代码
public class SingleInstance{
private SingleInstance(){}

private static SingleInstance singleInstance;

public SingleInstnce getSingleIntance(){
if(singleInstance == null){

singleInstance = new SingleInstance();
}
return singleInstance;
}
}


现在我们考虑另外一个问题,假如现在有连个线程,线程A和线程B,当线程A执行完判断,并且判断结果为空,但是还没有执行singleInstance = new SingleInstance()语句时,线程B获得了CPU资源,线程B也做了判断,由于线程A没有实例化对象,所以线程B继续执行,实例化了一个singleInstance对象,此时就有了一个singleIntance对象,然后线程A有获得了CPU资源,继续执行,由于线程A在之前已经执行过if语句,所以此时不在执行,依然认为singleInstance为空,所以也继续执行,实例化了一个singleInstance对象,此时就有了两个singleIntance对象,也不能满足只能实例化一个对象的需求,所以需要再次修改。

现在我们来加上同步锁就可以解决这个问题了

public class SingleInstance{
private SingleInstance(){}

private static SingleInstance singleInstance;

public SingleInstnce getSingleIntance(){
synchonized(SingleInstance.class){
if(singleInstance == null){
singleInstance = new SingleInstance();
}
}
return singleInstance;
}
}


这样就解决线程安全问题了,但是新的问题产生了,每次调用getSingleInstance()方法是都需要去判断同步锁,这样太浪费资源,所以仍然需要改进,我们给他加上双重判断,如果是空就执行同步锁判断,否则就不去执行了
public class SingleInstance{
private SingleInstance(){}

private static SingleInstance singleInstance;

public SingleInstnce getSingleIntance(){
if(singleInstance == null){
synchonized(SingleInstance.class){
if(singleInstance == null){
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
}


到此就完美解决了线程安全的问题,这是一种懒汉式的写法,另外一种是使用内部类来实现,先看代码
public class SingleInstance{
private SingleInstance(){}
private static class InnerClass
{
private static SingleInstance singleInstance = new SingleInstance();
}

public SingleInstance getSingleInstance(){
return SingleInstance.InnerClass.singleInstance;
}
}


可以看到我们在SingleInstance中添加了一个私有静态内部类InnerClass,在InnerClass中实例化了一个对象。然后在SingleInstance提供的共有方法中来返回了这个对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: