要點(diǎn)
- 某個類只能有一個實(shí)例
- 構(gòu)造器私有化
- 它必須自行創(chuàng)建這個實(shí)例
- 含有一個該類的靜態(tài)變量來保存這個唯一實(shí)例
- 必須自行先整個系統(tǒng)提供這個實(shí)例
- 對外提供獲取該實(shí)例對象的方式
- 直接暴露
- 用靜態(tài)變量的 get 方法獲取
- 對外提供獲取該實(shí)例對象的方式
常見幾種形式
- 餓漢式:直接創(chuàng)建對象不存在線程安全問題
- 直接實(shí)例化餓漢式(簡潔直觀)
- 枚舉式(最簡潔)
- 靜態(tài)代碼塊餓漢式(適合復(fù)雜實(shí)例化)
- 懶漢式:延遲創(chuàng)建對象
- 線程不安全(適用于單線程)
- 線程安全(適用于多線程)
- 靜態(tài)內(nèi)部列形式(適用于多線程)
- 直接實(shí)例化對象借卧,不管是否需要這個對象-餓漢式
/*
* 餓漢式
*(1)構(gòu)造器私有化
*(2)自行創(chuàng)建,并用靜態(tài)變量保存
*(3)向外提供這個實(shí)例
*(4)強(qiáng)調(diào)這是單例颜曾,用final修飾(這個變量只能賦值一次锋拖,之后不能修改)
*/
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1 (){
}
}
- 枚舉-jdk1.5之后-餓漢式
/*
*餓漢式
*枚舉類型:表示該類型的對象是有限的幾個
*我們可以限定為一個佛嬉,就成了單例
*/
public enum Singleton2{
INSTANCE
}
- 靜態(tài)代碼塊-餓漢式
/*
* 這種方式,適合那種需要從配置文件里面讀一堆信息來實(shí)例化迷守。
*/
public class Singleton3 {
public static final Singleton3 INSTANCE;
private String info;
static {
try {
Properties pro = new Properties(); // 從位于src目錄下的配置文件single.properties中讀取信息
pro.load(Sinfleton3.class.getClassLoader().getResourceAsStream("single.properties"));
INSTANCE = new Singleton3(pro.getPropertied("info"));
}catch(IOExcepption e){
throw new RuntimeException(e);
}
}
private Singleton3 (String info){
this.info = info;
}
}
4.線程不安全(適合單線程)-懶漢式
/*
* 懶漢式
*(1)構(gòu)造器私有化
*(2)靜態(tài)變量保存
*(3)提供一個靜態(tài)方法,獲取實(shí)例對象
*/
public class Singleton4 {
private static Singleton4 instance;
private Singleton4 (){
}
public static Singleton4 getInstance(){
if(instance == null){
//加上Thread.sleep(100);多線程情況下 會實(shí)例化兩個對象旺入。
instance = new Singleton4();
}
return instance;
}
}
- 線程安全(適合多線程)-懶漢式
/*
* 懶漢式
*(1)構(gòu)造器私有化
*(2)靜態(tài)變量保存
*(3)提供一個靜態(tài)方法盒犹,獲取實(shí)例對象
*/
public class Singleton5 {
private static Singleton5 instance;
private Singleton5 (){
}
public static Singleton5 getInstance(){
if(instance == null){//先判斷是否為空,再進(jìn)行加鎖。
synchronized(Singleton5.class){
//加上Thread.sleep(100);多線程情況下 會實(shí)例化兩個對象急膀。
instance = new Singleton5();
}
}
return instance;
}
}
- 靜態(tài)內(nèi)部類形式
/*
* 再內(nèi)部類被加載和初始化時沮协,才創(chuàng)建INSTANCE實(shí)例對象
* 靜態(tài)內(nèi)部類不會自動隨著外部類的加載和初始化而初始化,它是要單獨(dú)去加載和初始化的
* 因?yàn)槭窃趦?nèi)部類加載和初始化是,創(chuàng)建的卓嫂,因此是線程安全的慷暂。
*/
public class Singleton6 {
private Singleton6 (){
}
private static class Inner{
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}