1. 概念
- 保證一個類只有一個實例
- 并為該實例提供一個全局唯一的訪問節(jié)點
2. 懶漢式-方式一
2.1 代碼示例(方式一)
示例
public class Singleton03 {
/**
* 構造器私有化
*/
private Singleton03() {
}
/**
* 成員變量
*/
private static Singleton03 INSTANCE;
/**
* 對外提供公有的靜態(tài)方法
*/
public static Singleton03 getInstance() {
// 用到才加載
if (INSTANCE == null) {
INSTANCE = new Singleton03();
}
return INSTANCE;
}
}
public class SingletonTest03 {
public static void main(String[] args) {
Singleton03 instance = Singleton03.getInstance();
Singleton03 instance1 = Singleton03.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
2.2 優(yōu)缺點(方式一)
- 起到了Lazy Loading的效果,但是只能在單線程下使用。
- 如果在多線程下,一個線程進入了if(singleton==null)判斷語句塊,還未來得及
往下執(zhí)行炫隶,另一個線程也通過了這個判斷語句,這時便會產(chǎn)生多個實例。所以
在多線程環(huán)境下不可使用這種方式撑毛。
2.3 結論(方式一)
- 線程不安全,在實際開發(fā)中唧领,不要使用這種方式藻雌。
3. 懶漢式-方式二
3.1 代碼示例(方式二)
示例
public class Singleton04 {
/**
* 構造器私有化
*/
private Singleton04() {
}
/**
* 成員變量
*/
private static Singleton04 INSTANCE;
/**
* 對外提供公有的靜態(tài)方法
*/
public static synchronized Singleton04 getInstance() {
// 加入同步代碼,解決線程不安全問題
if (INSTANCE == null) {
INSTANCE = new Singleton04();
}
return INSTANCE;
}
}
public class SingletonTest04 {
public static void main(String[] args) {
Singleton04 instance = Singleton04.getInstance();
Singleton04 instance1 = Singleton04.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
3.2 優(yōu)缺點(方式二)
- 解決了線程不安全問題斩个。
- 效率太低了胯杭,每個線程在想獲得類的實例時候,執(zhí)行getinstance()方法都要進行同步受啥。而其實這個方法只執(zhí)行一次實例化代碼就夠了做个,后面的想想獲得該類實例,直接return就行了滚局。方法進行同步效率太低居暖。
3.3 結論(方式二)
- 線程安全,但效率太低藤肢,在實際開發(fā)中太闺,不推薦使用這種方式。
4. 懶漢式-方式三
4.1 代碼示例(方式三)
示例
public class Singleton05 {
private Singleton05() {}
private static Singleton05 INSTANCE;
public static Singleton05 getInstance() {
if (INSTANCE == null) {
synchronized (Singleton05.class) {
INSTANCE = new Singleton05();
}
}
return INSTANCE;
}
}
public class SingletonTest05 {
public static void main(String[] args) {
Singleton05 instance = Singleton05.getInstance();
Singleton05 instance1 = Singleton05.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
4.2 優(yōu)缺點(方式三)
- 這種方式嘁圈,本意是想對第四種實現(xiàn)方式的改進省骂,因為前面同步方法效率太低,改為同步產(chǎn)生實例化的的代碼塊最住。
- 但是這種同步并不能起到線程同步的作用钞澳。跟方式一實現(xiàn)方式遇到的情形一致,假如一個線程進入了if(singleton==null)判斷語句塊涨缚,還未來來得及往下執(zhí)行轧粟,另一個線程也通過了這個判斷語句,這時便會產(chǎn)生多個實例仗岖。
4.3 結論(方式三)
- 線程不安全逃延,在實際開發(fā)中,不要使用這種方式