Java中四种常见的单例模式的原理及各组成部分
1.恶汉式(创建类时创建单例,线程安全。永远需要这个对象,但是类加载时就会初始化这个对象,不确定是否使用时,饿汉会占用内存)
//static变量会在类加载时初始化
代码:
public class SHungry {
//静态属性,直接创建实例
private static SHungry instance= new SHungry();
private SHungry() {}
public static SHungry getInstance() {
return instance;
}
}
饿汉式提前实例化,没有懒汉式中多线程问题,但不管我们是不是调用getInstance()都会存在一个实例在内存中。
2.懒汉式(在需要的时候才创建,线程不安全。)
代码·:
public class Idler {
//静态属性,存储单例
private static Idler instance = null;
//私有的构造器,限制外部无法通过构造器创建实例
private Idler(){}
//静态方法,获取到单例
public static Idler getInstance() {
if(instance==null) {
instance=new Idler();
}
return instance;
}
}
在懒汉式中,有线程A和B,当线程A运行到第5行时,跳到线程B,当B也运行到5行时,两个线程的instance都为空,这样就会生成两个实例。解决的办法是同步。
3.DCL(在懒汉式上添加一道双重检查锁,使线程安全)
代码:
public class Idler {
private static Idler instance = null;
private Idler(){}
public static Idler getInstance() {// 多个线程可以共用这个方法
if(instance==null){
synchronized (Idler.class){
if(instance==null) {
instance=new Idler();
}
}
}
return instance;
}
}
4.枚举(枚举的创建由JVM保证,因此不会出现并发问题,构造器自动私有,外部不能创建,只能引用)
代码:
public enum SingletonEnum {
INSTANCE;
public String name;
public void doSomething(){
System.out.println("doSomething");
}
public static void main(String[] args) {
SingletonEnum.INSTANCE.doSomething();
}
}