单件模式:确保一个类只有一个实例,并提供一个全局访问点。
特点:
- 单例模式确保一个实例被创建,并且任意时刻都只有一个对象。
- 特征是构造函数为私有,然后声明一个私有静态成员作为类对象,对外提供一个静态类方法创建该对象
- 在创建对象时会先判断是否已经创建,若是则直接返回已经创建的对象,若没有则创建新对象
用途:
- 某些对象在程序运行过程中我们只需要一个,或只能生成一个,如线程池、注册表和代表打印机的对象等。如果创建多个实例就会发生异常。
- 如果将对象赋给某个全局变量(急切初始化),即事先就建立好对象,若对象在本次程序执行没有使用且占用很多资源就不是很合适
注意:
- 即使正确创建了单件模式类,但当使用多个类加载器时,每个类加载器定义了各自的命名空间,当不同的类加载器加载了同一个类,从整体程序上看,同一个类就会被加载多次,造成多个单件的存在。解决办法:自行指定同一个类加载器
- 单件类不能被继承,因为构造方法是私有的,如果这的把构造器的权限改变了,想要让子类能够顺利工作,基类必须实现注册表功能。即创建对应Map<String(class.name), instance>,用来记录类是否被创建以及被创建的实例
- 多线程问题:当有多个变成并发执行时,可能无法保证单件。解决办法:只要把getInstance()变成同步(synchronized)方法
- 并发与性能问题:解决:使用双重加锁检验机制,先检验是否创建,如未创建再同步(代码如下)
代码实现:
1 public class Singleton { 2 private volatile static Singleton uniqueInstance;//volatile 确保当uniqueInstance初始化为Singleton的实例时,多个线程可以正确的处理uniqueInstance变量。 3 private Singleton() {} 4 public static Singleton getInstance() { 5 if (uniqueInstance == null) {//只有第一次才会执行这里面的代码。也就是说第一次为同步,后来就是不作为了——这就是我们要的效果。 6 synchronized (Singleton.class) { 7 if (uniqueInstance == null) { 8 uniqueInstance = new Singleton(); 9 } 10 } 11 } 12 return uniqueInstance; 13 } 14 }