作者:Flieny 撰写日期:20190428
使用工具和技术:MyEclipse10、JDK1.7
在学习单例模式的时候,先了解一下它的适用场景。
- 需要生成唯一序列的环境(如淘宝订单)
- 需要频繁实例化然后销毁的对象(直播弹幕)
- 创建对象时耗时过多或者耗资源过多,但又经常用到的对象
- 方便资源相互通信的环境
目前有五种方式可以实现单例,它们分别是饿汉式、懒汉式、Double CheckLock双重锁机制、静态内部类、枚举类。
饿汉式,它在加载类的时候就首先创建好了一个对象实例,然后等待着调用,所以它叫饿汉式是有原因的,它很像饿汉一样,不管三七二十一先吃饱了再说,然后不管你调不调用,我都创建好了给你。
优点是线程安全的,调用效率高,但是不能延时加载。
public class SingletonOne{
//实例化这个类 SingletonOne自身这个类
//隐藏的自身的静态的实例
//final可以不用,但是在饿汉式这里需要使用final来保证安全
//饿汉式就是一加载就会实例自身
private static final SingletonOne INSTANCE=new SingletonOne();
//第一步 private私有 隐藏构造器
private SingletonOne(){ }
//第二步 把这个实例在定义一个私有的静态变量来放自身的实例
//第三步 创建静态方法,让外部可以获取实例
public static SingletonOne getInstance(){
return INSTANCE;
}
}
懒汉式,顾名思义,因为它在你使用啊这个对象的时候,它才会去检查这个对象是否存在,如果没有创建就马上创建,如果已经调用了,那么它就会返回这个实例,因此它被称为懒汉式。
优点是线程安全的,能延时加载,但是调用效率不高。
public class SingletonTwo {
//类初始化时,不初始化这个对象(延时加载,真正用的时候在创建)
private static SingletonTwo instance;//静态实例
private SingletonTwo(){}
//方法同步,调用效率低
//创建静态工厂方法,让外部可以获取实例
//synchronized 同步
public static synchronized SingletonTwo getInstance(){
if(instance == null){//如果这个实例等于空
instance= new SingletonTwo();//懒汉式就是你不去调用,就不会new一下,创建实例给你
}
return instance;
}
}
Double CheckLock 双重锁机制,它是由懒汉式单例上发展而来的,但由于JVM底层模型的原因,导致了它在执行若干次的时候会出错一次,就是这一次的出错会带来毁灭性的打击,因此不建议使用。
public class SingletonThree {
private volatile static SingletonThree instance;
//私有化构造器
private SingletonThree(){
}
//静态工厂方法,双重锁判断机制
public static SingletonThree newInstance(){
if(instance==null){ //如果instance为空
synchronized (SingletonThree.class){
//SingletonThree.class (锁)
//然后就同里面的一部分代码
//谁进来就先把下面的代码锁住用完再说
//然后后面来的只能等待第一个进去的用完
if(instance==null){
instance=new SingletonThree();
}//保证这段代码只能执行一次,只new一次就能保证是单例模式
}
}
return instance;
}
}
静态内部类,在类里面定义一个类叫做内部类,它主要会先把空间加载出来,但不会完全的加载出来,只要你在使用的时候才会完全的将内部类加载出来。
优点是线程安全的,调用效率高,可以延时加载。
public class SingletonFour {
//第二步 静态内部类
private static class SingletonClassInstance{
//只会将空间加载 但不会完全加载
//只有使用的时候才会完全加载
//只要使用的时候就会将内部类加载出来
private static final SingletonFour instance =new SingletonFour();
}
//第一步 私有化构造器
private SingletonFour(){
}
//第三步 静态工厂方法
public static SingletonFour getInstance(){
return SingletonClassInstance.instance;//调用内部父类的成员变量
}
}
枚举类,是单利模式中的一种,它是受到JVM底层保护的,JVM会在它执行的时候会保证此方法只能被调用一次,它的优点是能天然的防止反射和反序列化。
public class SingletonFive {
private SingletonFive(){
}
//使用枚举
private static enum Singleton{
INSTANCE;
private SingletonFive singleton; //私有化
//JVM会保证此方法绝对只能调用一次
private Singleton(){
singleton =new SingletonFive();//构建的时候new一下
}
public SingletonFive getInstance(){
return singleton;
}
}
//静态工厂方法 调用了Singleton→INSTANCE→getInstance
public static SingletonFive getInstance(){
return Singleton.INSTANCE.getInstance();
}
}
总结:以上就是学习单例模式的过程了,注意Double CheckLock 双重锁机制是已经过时的单例,一个大神发现了它的问题,它在执行若干此时会出错一次,不要小看这一次,也许就是这一次就可以将整个系统搞崩溃,如银行,银行在操作的时候出现一次错误,就会遭到毁灭性的打击。