设计模式故事——单例模式

4 单例模式

场景

附近有一个篮球专卖店太火了,想让小佑给配一个专用的微信客服(可以一对多)给客户解答疑惑,多次强调一个就够。

实现

这个容易,我建立一个客服类,new一个客服专门给他服务。
怎么保证同时只存在一个微信客服呢?客户只要一个,如果存在两个客服,另一个就得我掏钱了。

简单!我在客服类中用一个静态的私有客服变量 记录唯一客服。
构造函数设置为私有,只能通过自己初始化。
通过静态getInstance方法new客服,用户用类名.方法名的方式调用。
如果 客服变量为空,就new一个客服返回给用户,
如果客服变量不为空,就把当前的客服返回给用户。
问题解决收工。开开心心下班。

第二天,小佑发现办公室站着五个客服。
what?小佑查了一下日志,在昨天客服为空的时候,5个用户同时微信联系,导致new了5个客服。
这就是传说中的多线程问题么。
这波赔钱赚知识,就当换资源了,小亏。

多线程简单啊,加锁呗,看我一个 synchronized 甩在 getInstance脸上。
问题解决,下班。

第三天,刚上班,专卖店一个电话打过来,用户投诉,找客服反应太慢了,等好久才get到客服。
哎呦我去,怕不是加锁影响了性能,这可咋整,赶紧看看代码。
啊!其实只要微信客服已经存在了,多个客户可以同时联系他。
只不过在客服不存在的时候,多个客户同时联系就会触发多个new。

那我就可以来一手缩小同步块吧。
如果客服不为空我就直接return客服。
如果为空,我再加锁,加锁之后再判断一次是否为空,如果为空new,如果不为空,return客服。
看起来好像OK,但是如果并发量特别大的话,还是可能有点小问题。
如果可以容忍就这样吧,

不过本着学习进步的精神,再看看有没有别的方法。
小佑赶紧翻了翻书柜,拿出了一本落了一层灰的《JAVA语言程序设计》研究一下。
啊!也可以这样,如果声明客服类中的唯一客服变量为静态私有,并且初始化。
JVM会在类加载的时候马上创建一个对象,就可以保证在任何线程访问这个变量之前,客服已经被new出来了。

总结

单例模式确保一个类只有一个实例,且提供一个全局访问点。
不过看起来简单的单例模式,还是有点东西的。

猜你喜欢

转载自blog.csdn.net/tianyouououou/article/details/106246871