**方案1**
類初始化時創建,缺點是如果類過多或初始化程序耗時,啟動時間較長;過早創建實例,降低內存使用效率。
```
class Solution {
private Solution(){}
private static Solution instance = new Solution();
/**
* @return: The same instance of this class every time
*/
public static Solution getInstance() {
return instance;
}
};
```
**方案2**
延遲初始化,缺點是多線程時,如果同時判斷instance為null,可能會創建多個實例。
```
class Solution {
private Solution(){}
private static Solution instance = null;
/**
* @return: The same instance of this class every time
*/
public static Solution getInstance() {
if(instance == null){
instance = new Solution();
}
return instance;
}
};
```
**方案3**
多線程,為方法加鎖synchronized,缺點是如果同時有多個方法調用會依次進入,性能較低
```
class Solution {
private Solution(){}
private static Solution instance = null;
/**
* @return: The same instance of this class every time
*/
public static synchronized Solution getInstance() {
if(instance == null){
instance = new Solution();
}
return instance;
}
};
```
**方案4**
只有在instance未初始化時,多個線程在初始化之前會加鎖,instance不為null時不會加鎖;缺點是如果多個線程在`synchronized(Solution.class)`上等待時,如果第一個線程初始化釋放鎖后,第二個線程池進入還是會再次創建。
```
class Solution {
private Solution(){}
private static Solution instance = null;
/**
* @return: The same instance of this class every time
*/
public static Solution getInstance() {
if(instance == null){
synchronized(Solution.class){
instance = new Solution();
}
}
return instance;
}
};
```
**方案5**
在方案4的基礎上,如果第一個線程初始化釋放鎖后,其他線程池進入先判斷instance是否為null,如果不為null則不創建。
```
class Solution {
private Solution(){}
private static Solution instance = null;
/**
* @return: The same instance of this class every time
*/
public static Solution getInstance() {
if(instance == null){
synchronized(Solution.class){
if(instance == null){
instance = new Solution();
}
}
}
return instance;
}
};
```
**方案6**
由于重排序的問題, 對象的初始化分為3步,但是重排序時會先賦值后初始化
```
memory = allocate(); //1.分配內存空間
ctorInstance(memory); //2.初始化對象
instance = memory; //3.設置instance執行分配的地址
//由于重排序,執行時序如下:
memory = allocate(); //1.分配內存空間
instance = memory; //2.設置instance執行分配的地址
ctorInstance(memory); //3.初始化對象
```
這會導致線程1在第2步后賦值,然后線程2進入看到不為null就返回了,此時指針對應的內存還未初始化。因此需要加入volatile
```
private static volatile Solution instance = null;
```
**方案6**
我們需要的是延遲加載,并且只有一個線程初始化,因此可以考慮內部類,內部類在使用時才會初始化。
```
class Solution {
public static Solution getInstance() {
return Solution.InnerClass.getInstance();
}
private static class InnerClass{
private static Solution instance = new Solution();
public static Solution getInstance(){
return instance;
}
}
};
```
> 要點
* 構造函數是私有的
* 不要初始化時創建,要延遲創建;過早創建會降低內存使用效率