设计模式之 单例模式

单例模式的学习;

1.懒汉式:

public class Singleton {

private static Singleton singleton;

private Singleton(){};// 私有的.防止通过构造器实例化

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

加锁方式 上面这种直接加在方法上效率低,等同于下面, 锁住范围过大

public static Singleton getInstance(){

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

解决方式 双重锁:

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

为什么加双重锁?
假设我们去掉同步块中的是否为null的判断,有这样一种情况,假设A线程和B线程都在同步块外面判断了synchronizedSingleton为null,结果A线程首先获得了线程锁,进入了同步块,然后A线程会创造一个实例,此时synchronizedSingleton已经被赋予了实例,A线程退出同步块,直接返回了第一个创造的实例,此时B线程获得线程锁,也进入同步块,此时A线程其实已经创造好了实例,B线程正常情况应该直接返回的,但是因为同步块里没有判断是否为null,直接就是一条创建实例的语句,所以B线程也会创造一个实例返回,此时就造成创造了多个实例的情况。

 

2.饿汉式
public class Singleton {

private static Singleton singleton = new Singleton();

private Singleton(){};// 私有的.防止通过构造器实例化

public static Singleton getInstance(){
return singleton;
}
}

这种线程安全的, 但是类一加载就初始化了, 不管用不用得着. 容易造成内容损耗

3.登记者模式

public class Singleton {

private Singleton(){};// 私有的.防止通过构造器实例化

public static Singleton getInstance(){
return InnerSingleton.singleton;
}

private static class InnerSingleton(){
private static final Singleton singleton = new Singleton();
}
}

通过内部类实例化. 调用时候才会实例化一次. 静态内部类只有调用的时候才会加载

这是最好的模式

posted @ 2017-09-13 15:34  郝二驴  阅读(140)  评论(0编辑  收藏  举报