Java设计模式 单例模式 饿汉式和懒汉式

所谓单例模式,即外界不能创建对象,即外界不能new Object().实现很简单,私有化构造方法即可。(致萌新:平常通过new Xxx()创建对象即使用了类本身的构造方法,而private修饰的内容在类外部无法访问(反射可以暴力访问))

还需要外界能够引用对象,所以在类中仍需构建对象,并通过公共方法分享到外部

分享的都是对同一对象的引用,就叫单例模式。

而根据构建对象的时间问题,又分出饿汉式和懒汉式两种。

不管是否需要,对象都会被创建,这是饿汉式,饿疯了,来者不拒的感觉

package nuc.edu.ls;

public class Singleton {
	private static Singleton eagerSingleton=new Singleton();
	private Singleton(){
		
	}
	public static Singleton getInstance() {
		return  eagerSingleton;
	}

}

而懒汉式,就是表面上的意思,懒得不想动,当需要的时候才会取创建

因为是在公有方法中创建,如果多个线程同时访问的话,可能会创建出多个不同的对象,违背单例模式的原则。所有需要注意线程安全

1.同步锁写法

package nuc.edu.ls;

public class EagerSingleton {
    private static EagerSingleton eagerSingleton=null;
    private EagerSingleton() {
    }
    public static  synchronized EagerSingleton getInstance() {
    	if(eagerSingleton==null) {
    		eagerSingleton=new EagerSingleton();
    	}
    	return eagerSingleton;
    }
}

这种写法虽然解决了线程安全问题,但同一时刻只有一个线程能获取对象,存在了效率低下的问题

2.双重校验锁写法

package nuc.edu.ls;

public class EagerSingleton2 {
    private static volatile EagerSingleton2 eagerSingleton=null;
    private EagerSingleton2() {
    }
    public static   EagerSingleton2 getInstance() {
    	if(eagerSingleton==null) {
    		synchronized (EagerSingleton2.class) {
				if(eagerSingleton==null) {
					eagerSingleton=new EagerSingleton2();
				}
			}
    	}
    	return eagerSingleton;
    }
}

volatile用法禁止了指令重排序,防止获得未完成初始化的对象。volatile保证了可见性和禁止了指令重排序,有兴趣的小伙伴可以研究研究

3.内部类写法

package nuc.edu.ls;

public class EagerSingleton3 {
    private static EagerSingleton3 eagerSingleton=null;
    private static class  getSingleton{
    	static final EagerSingleton3 EAGER_SINGLETON3=new EagerSingleton3();
    }
    private EagerSingleton3() {
    }
    public static  synchronized EagerSingleton3 getInstance() {
    	return getSingleton.EAGER_SINGLETON3;
    }
}

因为只有getInstance可以访问内部类,而对象在访问内部类后被创建(饿汉式的特性,根据JVM类的加载过程得出)。而身为被final修饰的对象,只有第一次才会被创建。而后的n次,根据常量的特性,从常量池获取,而不是开辟新的空间。(单例模式的特性)

你可能感兴趣的:(Java设计模式 单例模式 饿汉式和懒汉式)