單例模式的幾種方式
首先是餓漢式:
public class Singleton {
private static Singleton s = new Singleton();
//遮蔽外部的new
private Singleton() {
super();
}
//提供一個全域性的訪問點
public static Singleton getInstance() {
return s;
}
public void A(){
System.out.println("xixi");
}
}
public class SingletonTest {
public static void main(String[] args) {
/* Singleton s1 = Singleton.s;
Singleton s2 = Singleton.s;*/
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 .equals(s2)); //true
s1.A();
}
對於懶漢式,在類載入的過程中就會去建立這個類的例項,並沒有達到延遲載入的效果,但是執行緒是安全的!
然後是懶漢式:跟餓漢式的區別就是沒有在一開始就初始化了,
//會在這個方法裡面初始化
public synchronized static Singleton getInstance() {
if(s==null) {
s = new Singleton();
}
return s;
}
注意:沒有加鎖的懶漢式是執行緒不安全的,但是如果加了鎖之後,每個執行緒執行該方法的時候都會進行執行緒等待,就會導致同步情況下執行效率低!
所以只需要判斷第一次是否為空的時候需要加鎖,其餘時候是不需要加鎖的,為了解決這個問題,就有了雙重驗證式!
public static Singleton getInstance() {
if(s==null) {
synchronized(Singleton.class) {
if(s== null) {
s=new Singleton();
}
}
s = new Singleton();
}
return s;
}
注:雙重驗證式具有延遲載入,執行緒安全,同步情況效率高,唯一就是實現相對複雜!
對於類載入方式,具有以上所有的優點,並且實現簡單
public class Singleton {
//遮蔽外部的new
private Singleton() {
}
//靜態內部類,用於建立唯一的Singleton的例項
private static class OnlyInstanceHolder{
static private Singleton Only = new Singleton();
}
//公開的唯一訪問點
public static Singleton getInstance() {
return OnlyInstanceHolder.Only;
}
唯一的缺陷是不能防止反序列化!