阅读时间: 15分钟
单例模式 (singleton pattern)
它存在的目的是可以限制物件(Object)产生的数量,只容许产生一个物件(Objest)。
那就是只有一个实例(Instance)。
往后每次调用都是指向相同的物件(Object)。
public class Singleton{ private static Singleton uniqueInstance; // 使用private Consructor 确保类别Singleton 的物件(Object)只能透过 API – method : getInstance()。private Singleton(){// 这里可以有很多code,所以建立物件(Object)可能需要很多资源/时间。}// 因为Constructor已经private,所以需要以下方法让其他程式调用这个类别。 public static Singleton getInstance() { // 第一次被呼叫时,才建立物件(Object) if(uniqueInstance == null ) {uniqueInstance = new Singleton();} return uniqueInstance; } }
以上程式在某些情况运行时是没问题,但如果是在多执行绪(Multi Thread)的情况下呼叫getInstance(),可能第一个执行绪(Thread)跑到instance = new Singleton()时,另一个执行绪(Thread)在 if(uniqueInstance==null) 判断时也进入迴圈(loop), 最后同一时间产生了多于一个的物件(Object)。
为了解决这个情况,我们需要对刚才的程式进行修改。
在程式内加上同步(synchronized)关键字
public class Singleton{ private static Singleton uniqueInstance; // 使用private Consructor 确保类别Singleton 的物件(Object)只能透过 API – method : getInstance()。private Singleton(){// 这里可以有很多code,所以建立物件(Object)可能需要很多资源/时间。}// 因为Constructor已经private,所以需要以下方法让其他程式调用这个类别。 public static synchronized Singleton getInstance() { // 使用 synchronized 关键字避免多于一个Thread 进入 if(uniqueInstance == null ) {uniqueInstance = new Singleton();} return uniqueInstance; } }
不过同步(synchronized)关键字会导致程式的执行效能会变差,(不适合用于像伺服器这种有很多执行绪(Multi Thread)的程式上)。
所以可以使用双重检查锁定模式(Double-check Locking),加快程式的效能。
双重检查锁定模式(Double-check Locking)
就是将synchronized搬到getInstance方法内。
public class Singleton{ private static Singleton uniqueInstance; // 使用private Consructor 确保类别Singleton 的物件(Object)只能透过 API – method : getInstance()。private Singleton(){// 这里可以有很多code,所以建立物件(Object)可能需要很多资源/时间。}// 因为Constructor已经private,所以需要以下方法让其他程式调用这个类别。 public static Singleton getInstance() { // 使用 synchronized 关键字避免多于一个Thread 进入 if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return uniqueInstance; } }