一,简单单例模式 (不推荐)
public class SimpleInstance {
//简单单例模式
//并发下会产生多个实例,不推荐
private static SimpleInstance simpleInstance;
private SimpleInstance() {
//构造器必须私有 不然直接new就可以创建,违背了单例的原则
}
public static SimpleInstance getSimpleInstance() {
if (simpleInstance == null) {
simpleInstance = new SimpleInstance();
}
return simpleInstance;
}
}
二,懒汉单例模式 根据业务场景(比较推荐)
public class SimpleInstance {
//懒汉单例模式,在方法上加同步锁
//懒汉式的特点是,用到这个实例时才去调用方法实例化。因为我们把整个方法加锁了,实现了线程安全,
//但是在多线程的情况下效率很低
private static SimpleInstance simpleInstance;
private SimpleInstance() {
//构造器必须私有 不然直接new就可以创建,违背了单例的原则
}
public static synchronized SimpleInstance getSimpleInstance() {
if (simpleInstance == null) {
simpleInstance = new SimpleInstance();
}
return simpleInstance;
}
}
三,饿汉单例模式 根据业务场景(比较推荐)
public class SimpleInstance {
//饿汉单例模式 因为被static修饰 所以在JVM装载类的时候,这个对象就会被初始化,所以是线程安全,
//不管会不会用到,都会被初始化,所以被称为饿汉模式,
private static final SimpleInstance simpleInstance=new SimpleInstance();
private SimpleInstance(){
//构造器必须私有 不然直接new就可以创建,违背了单例的原则
}
public static SimpleInstance getSimpleInstance(){
return simpleInstance;
}
}
四,双锁校验单例模式 根据业务场景(非常推荐)
public class SimpleInstance {
//双锁校验单例模式,
//被volatile修饰的变量,实现了“可见性”,既当内容发生改变时,所有线程都能看到。
private static volatile SimpleInstance simpleInstance;
private SimpleInstance(){
//构造器必须私有 不然直接new就可以创建,违背了单例的原则
}
public static SimpleInstance getSimpleInstance(){
if(simpleInstance==null){
//这一步是为了拒绝其他线程重复进入下面的同步锁代码,
//这也是为什么不跟懒汉模式一样把同步锁加载方法上的原因,减少性能开销
synchronized (SimpleInstance.class){
//这一步加同步锁,是为了防止两个线程同时进入,创建多个对象
if(simpleInstance==null){
//这里第二次判空,是为了防止第一个线程拿到上面的同步锁之后,第二个线程刚好赶到,
//并被阻塞在这里,当第一个线程new 创建完实例对象后,
//此时simpleInstance已经不是空了,所以需要二次判空。
simpleInstance = new SimpleInstance();
}
}
}
return simpleInstance;
}
}