單例模式,有「懶漢式」和「餓漢式」兩種。安全
懶漢式多線程
單例類的實例在第一次被引用時候才被初始化。性能
public class Singleton { private static Singleton instance=null; private Singleton() { } public static Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
餓漢式this
單例類的實例在加載的時候就被初始化。線程
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance(){ return instance; } }
在單線程程序中,上面兩種形式基本能夠知足要求了,可是在多線程環境下,單例類就有可能會失效,這個時候就要對其加鎖了,來確保線程安全。code
對線程加鎖用的synchronized關鍵字,這個關鍵字的用法主要也分爲兩種:對象
一種是加在方法名以前,形如:synchronized methodeName(params){……};blog
二是聲明同步塊,形如:synchronized(this){……};get
下面是對懶漢式單例類加上線程同步的實現:同步
同步方法:
public class Singleton { private static Singleton instance=null; private Singleton() { } public synchronized static Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
這種方式效率比較低,性能不是太好,不過也能夠用,由於是對整個方法加上了線程同步,其實只要在new的時候考慮線程同步就好了,這種方法不推薦使用。
同步代碼塊:
public class Singleton { private static Singleton instance; private final static Object syncLock = new Object(); private Singleton() { } public static Singleton getInstance(){ if (instance == null) { synchronized (syncLock) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
synchronized同步塊括號中的鎖定對象是採用的一個無關的Object類實例,而不是採用this,由於getInstance是一個靜態方法,在它內部不能使用未靜態的或者未實例的類對象,所以也能夠用下面的方法來實現:
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance(){ if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }