@toc
饿汉模式
无线程安全问题, 但是没办法懒加载
package com.mine;
/**
* 饿汉模式, 无法懒加载
*/
public class SingletonObject {
private static final SingletonObject instance = new SingletonObject();
private SingletonObject(){
}
public static SingletonObject getinstance(){
return instance;
}
}
懒汉模式
可以懒加载, 但是有线程安全问题需要处理
- 方式1
package com.mine;
/**
* 懒汉模式
*/
public class SingletonObject {
private static SingletonObject instance;
private SingletonObject(){
}
public synchronized static SingletonObject getinstance(){
if(null == instance){
instance = new SingletonObject();
}
return instance;
}
}
这种会有性能问题, 每次进来都要加同步锁, 变成了串行
- 方式2
package com.mine;
/**
* 懒汉模式, 两次判断
*/
public class SingletonObject {
private static volatile volitile SingletonObject instance;
private SingletonObject(){
}
public static SingletonObject getinstance(){
// 这样的话不用每次都加锁了
if(null == instance){
synchronized(SingletonObject.class){
if(null == instance){
instance = new SingletonObject();
}
}
}
return instance;
}
}
这种方式, 不用每次进来都加锁, 解决了效率问题, 但是有很小概率会空指针, 因为创建实例后, 需要赋给静态变量, 可能jvm会自动优化, 重排序, 导致instance还没初始化完成, 另外一个线程就来调用这个实例了, 所以需要加上volatile关键字
- 方式3(比较优雅的方式)
package com.mine;
/**
* 懒汉模式, 两次判断
*/
public class SingletonObject {
private static volatile SingletonObject instance;
private SingletonObject(){
}
private enum Singleton {
INSTANCE;
private final SingletonObject instance;
Singleton(){
instance = new SingletonObject();
}
public SingletonObject getInstance(){
return instance;
}
}
public static SingletonObject getinstance(){
return Singleton.INSTANCE.getInstance();
}
}
采用枚举的方式, 枚举不存在线程安全性问题