简介
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
所谓“懒汉式”与“饿汉式”的区别,是在与建立单例对象的时间不同。
目的
1,一个类只能有一个实例
2,自己创建这个实例
3,整个系统都要使用这个实例
例: 在下面的对象图中,有一个"单例对象",而"客户甲"、"客户乙" 和"客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。
![](https://i-blog.csdnimg.cn/blog_migrate/18fcd00068e85d3c1dc892b3e81246ef.jpeg)
实例
一、懒汉式
“懒汉式”是在你真正用到的时候才去建这个单例对象: 比如:
public class Singleton{
private static Singleton singleton = null;
public static synchronized getInstance(){
if(singleton==null)
{
singleton = new Singleton();
}
return singleton;
}
}
二、饿汉式
“饿汉式”是在不管你用的用不上,一开始就建立这个单例对象: 比如:
public class Singleton{
private static Singleton singleton = new Singleton ();
private Singleton (){}
public Singleton getInstance(){ return singletion; }
}
三、静态内部类
加载时不会初始化静态变量INSTANCE,因为没有主动使用,达到Lazy loading
class InternalSingleton{
private static class SingletonHolder{
private final static InternalSingleton INSTANCE=new InternalSingleton();
}
private InternalSingleton(){}
public static InternalSingleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
四、枚举
《Effective Java》作者推荐使用的方法,优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
为什么能避免多线程同步问题以及防止反序列化重新创建新的对象,请点击:http://blog.csdn.net/zhushuai1221/article/details/51780769
public enum SingletonWithEnum {
/**
* @author boker
*/
instance;
public SingletonWithEnum(){
//构造方法
}
public static SingletonWithEnum getInstance() {
return instance;
}
}
五、 双重校验锁
双重检验锁模式(double checked locking pattern),是一种使用同步块加锁的方法。程序员称其为双重检查锁,因为会有两次检查 instance == null
,一次是在同步块外,一次是在同步块内。为什么在同步块内还要再检验一次?因为可能会有多个线程一起进入同步块外的 if,如果在同步块内不进行二次检验的话就会生成多个实例了。
class LockSingleton{
private volatile static LockSingleton singleton;
private LockSingleton(){}
public static LockSingleton getInstance(){
if(singleton==null){
synchronized(LockSingleton.class){
if(singleton==null){
singleton=new LockSingleton();
}
}
}
return singleton;
}
}
相关阅读:1、单例模式,防止反射和反序列化漏洞
2、面试之单例模式
3、单例模式的5种实现方式,以及在多线程环境下5种创建单例模式的效率