系统中只需要一个实例的情况需要使用单例模式。
有8中写法,之后两种是完美无缺的,一般使用的都是存在问题的
饿汉模式
第一种
静态实例字段,构造方法私有化,只能通过设置的getInstance方法获得实例
private static final Apple INSTANCE = new Apple();
private Apple(){}
public static Apple getInstance(){return INSTANCE;}
第二种
静态语句块
static{INSTANCE = new Apple}
private Apple(){}
public static Apple getInstance(){return INSTANCE;}
缺点是:无论使用与否,类都会被实例化。
懒汉模式
第三种
单线程的单例懒汉模式
private static Apple INSTANCE;
private Apple(){}
public static Apple getInstance(){
if(INSTANCE==null){
INSTANCE = new Apple();
}
return INSTANCE;
}
缺点:单线程没问题,多线程存在问题,可能创建多个实例
第四种
加锁解决上一种多线程可能出现的问题
private static Apple INSTANCE;
private Apple(){}
public static synchornized Apple getInstance(){
if(INSTANCE==null){
INSTANCE = new Apple();
}
return INSTANCE;
}
缺点:效率降低
第五种
试图减少同步代码块来提高效率,结果不可行
private static Apple INSTANCE;
private Apple(){}
public static Apple getInstance(){
if(INSTANCE==null){
synchronized (Apple.class){
INSTANCE = new Apple();
}
}
return INSTANCE;
}
不能实现单例
第六种
双重校验锁
private static Apple INSTANCE;
private Apple(){}
public volatile static Apple getInstance(){
if(INSTANCE==null){
synchronized (Apple.class){
if(INSTANCE==null){
INSTANCE = new Apple();
}
}
}
return INSTANCE;
}
最完美的
静态内部类
第七种
把静态实例的初始化放在内部类中可以实现懒汉模式
public class Apple{
private Apple(){}
private static class InnerClass{
private final static Apple INSTANCE = new Apple;
}
public static Apple getInstanve(){
return Inner.INSTANCE;
}
}
jvm实现类加载只加载一次
第8种
effect java中枚举单例
线程同步且防止反序列化
public class Apple{
INSTANCE;
public static Apple getInstanve(){
return INSTANCE;
}
}