美文网首页
[Design Pattern]单例模式

[Design Pattern]单例模式

作者: 浩成聊技术 | 来源:发表于2018-07-19 19:25 被阅读12次

什么是单例模式

单例模式(Single Pattern),被单例的对象只能有一个实例存在。单例模式的实现方式是,一个类只能返回对象的一个引用和一个获得该唯一实例的方法(此方法必须是静态方法)。

为什么要使用单例设计模式

通过单例模式,可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源

单例模式分类及其代码实现

1.饿汉模式

一开始就创建一个实例。虽然较为简单和常见。但有一个明显的缺点,就是不管有没有调用过获得实例的方法,都会创建一个实例。

public class Single {
    private static final Single single = new Single();
    private Single(){}
    public static Single getSingle(){
        return single;
    }
}
2.懒汉模式

他改进了上述"饿汉模式"的不足之处,调用getSingle() 方法时首先判断实例是否为空,为空才创建实例,并且是调用方法时才创建

public class Single {
    private static Single single;
    private Single(){}
    public static Single getSingle(){
        if (single == null){
            single =  new Single();
        }
        return single;
    }
}
3.线程安全的懒汉模式

懒汉模式也存在问题。那就是如果有多个线程并行调用getSingle() 方法的时候,还是会创建多个实例,那单例子模式就失效了。所以在此基础上设置线程同步(关键子synchonized)。synchronized的作用就是保证在同一时刻最多只有一个线程运行,这样就避免了多线程带来的问题 。

public class Single {
    private static Single single;
    private Single(){}
    public static synchronized Single getSingle(){
        if (single == null){
            single =  new Single();
        }
        return single;
    }
}
4.双重检验锁

上述解决方法,也不是完美的。每次调用getSingle()时都要进行线程同步,考虑一下这种情况,single对象已经创建了,本来直接返回对象使用即可,但却又要进行线程同步。
于是在此基础之上,又有了双重检验锁的方法

public class Single {
    private volatile static Single single;
    private Single(){}
    public static Single getSingle(){
        if (single == null){
            synchronized (Single.class){
                if(single == null){
                    single = new Single();
                }
            }
        }
        return single;
    }
}
  • 注意

还需要给实例加一个 volatile 关键字,它的作用就是防止编译器自行优化代码,以保证代码的运行顺序是固定不变的。这涉及到JVM的代码优化机制。

5.静态内部类

上述方法不断改进,有点复杂,其实完全可以通过静态内部类来保证线程安全。

public class Single {
    private static class SingleHoder{
        private static final Single single = new Single();
} 
    private Single(){}
    public static Single getSingle(){
        return SingleHoder.single;
    }
}

Single类是私有的,除getSingle()方法*之外没有其他方式可以访问到实例,而且只有调用改方法时才会去创建实例对象。

6.枚举

这种方法最为简单。我们可以通过Single.INSANCE来访问实例,并且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题。

public enum  Single {
    INSTANCE;
    public void whateverMethod(){};
}

关于作者

个人博客: http://yhch.xyz

相关文章

网友评论

      本文标题:[Design Pattern]单例模式

      本文链接:https://www.haomeiwen.com/subject/orcxmftx.html