本站公告

  • 版权说明:网站所有内容均来自互联网用户共享内容,不代表波克斗地主立场,若侵犯您的权益,请与我们联系。

  • 投诉/建议:欢迎与波克斗地主合作、投诉、建议,意见可以发送详细内容至邮件:15983226@qq.com 。

单例模式,你真的写对了吗?

看公司代码的时候发现项目中单例模式应用挺多的,并且发现的两处单例模式用的还是不同的方式实现的,那么单例模式到底有几种写法呢?单例模式看似很简单,但是实际写起来却问题多多。

本文大纲

什么是单例模式饿汉式创建单例对象懒汉式创建单例对象单例模式的优缺点单例模式的应用场景

什么是单例模式

确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,并且有两种创建方式,一种是饿汉式创建,另外一种是懒汉式创建

饿汉式创建单例模式

饿汉式创建就是在类加载时就已创建好对象,而不是在需要时在创建对象

publicclassHungrySingleton{privatestaticHungrySingletonhungrySingleton=newHungrySingleton;/***私有构造函数,不能被外部所访问*/privateHungrySingleton{}/***返回单例对象**/publicstaticHungrySingletongetHungrySingleton{returnhungrySingleton;}}

说明:

构造函数私有化,保证外部不能调用构造函数创建对象,创建对象的行为只能由这个类决定只能通过getHungrySingleton方法获取对象HungrySingleton对象已经创建完成

缺点:

如果getHungrySingleton一直没有被使用到,有点浪费资源

优点:

由ClassLoad保证线程安全

懒汉式创建单例模式

懒汉式创建就是在第一次需要该对象时在创建

存在错误的懒汉式创建单例对象根据定义很容易在上面饿汉式的基础上进行修改

publicclassLazySingleton{privatestaticLazySingletonlazySingleton=null;/***构造函数私有化**/privateLazySingleton{}privatestaticLazySingletongetLazySingleton{if{returnnewLazySingleton;}returnlazySingleton;}}

说明:

构造函数私有化当需要时才创建

嗯,好像没什么问题,但是当有多个线程同时调用getLazySingleton方法时,此时刚好对象没有初始化,两个线程同时通过lazySingleton==null的校验,将会创建两个LazySingleton对象。必须搞点手段使getLazySingleton方法是线程安全的

synchronize或Lock

很容易想到使用synchronize或Lock对方法进行加锁使用synchronize:

这两种方式虽然保证了线程安全,但是性能较差,因为线程不安全主要是由这段代码引起的:

if{lazyLockSingleton=newLazyLockSingleton;}

给方法加锁无论对象是否已经初始化都会造成线程阻塞。如果对象为null的情况下才进行加锁,对象不为null的时候则不进行加锁,那么性能将会得到提升,双重锁检查可以实现这个需求

双重锁检查

在加锁之前先判断lazyDoubleCheckSingleton==null是否成立,如果不成立直接返回创建好的对象,成立在加锁

说明:

为什么需要对lazyDoubleCheckSingleton添加volatile修饰符

(责任编辑:波克斗地主)