1、在private构造函数前,自己先创建一个唯一单例,然后在内部创建一个能获得单例的方法,让外部只能调用到这个唯一单例。
缺点是:不管后面是否使用它,都会被加载。
2、那如果我们使用静态代码块呢?在我们的静态代码块中创建唯一实例
发现跟玩法一差不多。
3、那我们还是希望这个实例,只有当我们要使用它的时候再加载它,这样就引出了懒加载的方式
但是这样,在多线程情况下,会造成线程安全问题。
4、那我们为了解决这个线程安全问题,在创建实例的方法加上一个线程同步的关键字synchronized关键字,是不是就行了呢?
这样确实是成功了,咱们的线程安全是得到了保障,可每一次调用这个方法,我们就要进行一次加锁的判断,势必又会导致效率的降低。那我们还有没有更好的办法呢?
5、如果我不把锁加在方法上,而是加在内部,减少同步代码块,是不是效率就能得打提高呢?
效率得到提高,但是线程安全又得不到保证了。那这个线程安全问题又是什么导致的呢?还是我们if语句和锁未能一体化操作的原因。
6、那既然这样,我在锁后面在进行一次实例对象是否为空的检查,是不是就能解决线程安全了?
这里不难发现,线程安全了,效率也得到了提升。那我的第一次if判断还需要吗?是不是去掉后,会更好呢?其实不是,正因为有了第一次的if判断,才为我们减少很多次不必要的上锁操作。
7、那我还想要优化,怎么办?我们可以引入匿名内部类,确保它在不被调用时,就不会被加载,这样既能利用到jvm的加载机制,保证单例,又能确保线程安全,还起到懒加载的作用。
但这样,就结束了吗?不,Java的创始作者之一,提供一种更为优化的方式。
8、那就是使用枚举,因为枚举类型也没有构造函数,它就是唯一的。
这样不仅能保证线程安全,效率提升外,还可以反序列化,可以说是这里面最优秀的方法了,但又由于它是枚举类型,在我们使用时,会很别扭。
单例模式的各种玩法
最新推荐文章于 2024-07-13 22:56:10 发布