1、定义:单件模式确保一个类只有一个实例,并提供一个全局访问点。
2、实现方式:
- 经典方式:
public class Singleton{ private static Singleton uniqueInstance; private Singleton(){} public static Singleton getInstance(){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }
经典方式的缺陷是如果多线程同时使用,可能会导致创建了多个实例,违反了单件模式的意义,为了解决多线程灾难问题,可以加同步关键字,如下程序所示。
- 多线程方法(同步:该方法保证每个线程在进入方法前,要先等候别的线程离开该方法才可以。即不会有两个线程同时进入这个方法):
public class Singleton{ private static Singleton uniqueInstance; private Singleton(){} public static synchronized Singleton getInstance(){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }
该方法虽然解决了多线程灾难问题,但是又会出现性能问题,因为只有在第一次创建单例对象时需要同步,之后每一次调用该方法都会使用同步,但是这个时候就会造成多线程等待当前线程调用的情况,也就是性能问题。如果说不需要考虑性能问题的话,可以直接使用该方法,这是最好的,但是如果说,真的需要解决多线程灾难且不能引起性能问题,可以采用如下两种方法。
- 线程安全:
public class Singleton{ private static Singleton uniqueInstance = new Singleton(); private Singleton(){} public static synchronized Singleton getInstance(){ return uniqueInstance; } }
该方法方法是在静态初始化器中创建单件,这保证了线程安全。
- 双重检查加锁:
public class Singleton{ private volatile static Singleton uniqueInstance; private Singleton(){} public static synchronized Singleton getInstance(){ if(uniqueInstance == null){ synchronized (Singleton.class){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
该方法保证首先检查实例是否已经创建了,如果尚未创建,才进行同步,否则直接使用已创建实例即可。这个方法既保证了线程安全又保证了性能问题。
volatile关键词确保:当uniqueInstance变量被初始化城Singleton实例时,多个线程正确地处理uniqueInstance变量。
参考资料
[1] head first 设计模式