**方案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;
}
}
};
```
> 要点
* 构造函数是私有的
* 不要初始化时创建,要延迟创建;过早创建会降低内存使用效率