一、餓漢式
1.常規創建法
/*
* 餓漢式:
* 在類初始化時直接創建實例對象,不管你是否需要這個對象都會創建
*
* (1)構造器私有化,禁止new對象保持對象唯一
* (2)自行創建,並且用靜態變量保存
* (3)向外提供這個實例
* (4)強調這是一個單例,我們可以用final修改
*/
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1() {
}
}
2.枚舉法
/*
* 枚舉類型:表示該類型的對象是有限的幾個
* 我們可以限定爲一個,就成了單例
*/
public enum Singleton2 {
INSTANCE
}
獲取測試
public class TestSingleton1 {
public static void main(String[] args) {
Singleton1 s = Singleton1.INSTANCE;
System.out.println(s);
}
}
二、懶漢式
1.常規創建法
/*
* 懶漢式:
* 延遲創建這個實例對象
*
* (1)構造器私有化
* (2)用一個靜態變量保存這個唯一的實例
* (3)提供一個靜態方法,獲取這個實例對象
*/
public class Singleton4 {
private static Singleton4 instance;
private Singleton4(){
}
public static Singleton4 getInstance(){
if(instance == null){
instance = new Singleton4();
}
return instance;
}
}
上面這種方法在多線程時會遇到問題
2.加鎖
public class Singleton5 {
private static Singleton5 instance;
private Singleton5(){
}
public static Singleton5 getInstance(){
if(instance == null){
synchronized (Singleton5.class) {
if(instance == null){
instance = new Singleton5();
}
}
}
return instance;
}
}
3.內部類創建法
/*
* 在內部類被加載和初始化時,才創建INSTANCE實例對象
* 靜態內部類不會自動隨着外部類的加載和初始化而初始化,它是要單獨去加載和初始化的。
* 因爲是在內部類加載和初始化時,創建的,因此是線程安全的
*/
public class Singleton6 {
private Singleton6(){
}
private static class Inner{
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}