设计模式学习之二单例模式

2020-02-26

单例模式Singleton

1.定义

保证一个类只有一个实例,并提供一个访问它(这个实例)的全局访问点。本质是控制实例数目。

1.1功能

保证这个类在运行期间只会被创建一个实例。

1.2单例的范围

如果一个虚拟机里有多个ClassLoader,且每个ClassLoader都装载一次Singleton,那么就可能会创建多个实例。如果有多个虚拟机且每个虚拟机都装载一次Singleton那么肯定就会创建多个实例了。

2.思路

通过一个类能够创建多个实例,根源在于它的构造方法是公开的,只要它的构造方法公开,类外就可以通过它构造多个实例。所以如果要控制实例的创建,就要控制构造方法的权限

可以通过私有构造方法的形式收回权限。类里面提供一个公开方法返回实例(这个实例由这个类自己创建)

Singleton
private Singleton()
public Singleton getInstance()

懒汉模式

//第一次需要它的时候才创建一个实例,然后返回

//后面如果再次需要获取实例就要判断 /**有没有创建过**/

public class Singleton {
    private static Singleton s=null;
    private Singleton(){
    //
    }
    //因为要判断是否创建过,所以要考虑多线程的问题
    public static synchronized Singleton getInstance(){
        if(s==null){
            s=new Singleton();
        }
        return s;
    }
    //other methods and fields
}

---引出延迟加载思想

if (资源未加载){

//加载资源

}

一开始不加载资源,等到需要它的时候再加载,尽可能的节约资源

但是每次调用资源都要判断是不是已经加载过了

饿汉模式

//装载这个类的时候就已经创建了一个实例,以后需要获取实例直接把它返回就好了

public class Singleton {
    private static Singleton s=new Singleton();
    private Singleton(){
       // 
    }
    public static Singleton getInstance(){
        return s;
    }
    //other methods and fields
}

--时间和空间和线程安全
 

懒汉模式是典型的时间换空间(每次都要判断是不是已经加载过资源,浪费了判断时间)

从线程安全来说 不加同步的懒汉线程也是不安全的,如果并发情况下多个线程访问了getInstance就可能会创建多个实例

懒汉--创建实例 怎么线程安全呢{

1.加同步但是这样会降低访问速度

2.双重加锁,资源volatile;先判断实例可存在,存在就返回;不存在再

synchronized(Singleton.class){
	if(资源不存在){
		//创建资源
	}
}//这样就创建好资源后就不需要再同步了

也可以通过私有静态内部类里将资源静态化 的方式返回资源

//static 内部类的成员由jvm管理 保证只加载一次