-
单例模式:确保一个类只有一个实例,并提供一个全局访问点。
-
类图
- Singleton类,其构造方法(函数)是私有的,然后对外公开一个getInstance()方法来获取实例。
-
经典模式的Singleton(单例)模式实现
public class Singleton{ private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
- instance 是静态变量,因为构造方法是private(私有的),所有只有在Singleton类内才可以调用构造器。在单例模式中对外提供getInstance()方法来创建Singleton的实例,当首次调用getInstance()方法时,会执行instance = new Singleton();实例化对象,并返回这个实例。
- getInstance()方法是一个类方法,所以可以在代码的任何地方调用Singleton.getInstance()方法,这和访问全局变量一样简单。
- 单例模式可以延迟实例化,只有在调用getInstance()方法的时候,实例化对象。
- 单例模式的优点
- 提供了对唯一实例的受控访问。
- 唯一实例可以节约系统资源,对于一些需要频繁创建和销毁的对象可以提高系统的性能。
- 多线程的单例模式
public class Singleton{ private Singleton instance; private Singleton(){ } public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
通过增加synchronzied关键字到getInstance()方法中,每个线程在进入这个方法中,会等待其它线程离开该方法再去执行,不会有多个线程可以同时进入该方法。但是这种同步会在每次调用该方法的时候检查是否有其它线程执行,这样会降低系统的性能,可以使用"双重检查加锁",减少使用同步。
-
“双重检查加锁”
public class Singleton{ private volatile static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ instance = new Singleton(); } } return instance; } }
valatile关键字保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
-
“懒汉式”写法
public class Singleton{ private static Singleton instance; private Singleton(){ } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton();//懒汉式写法 } return instance; } }
-
"饿汉式"写法
public class Singleton{ private static Singleton instance = new Singleton(); private Singleton(){ } public static Singleton getInstance(){ return instance; } }
-
总结
- 单例模式确保程序中只有一个类只有一个实例
- 对外提供了实例化的方法
- 多线程使用单例模式的时候要小心的选择适当的方案来实现单例