标签:
欢迎来到这一站 单件模式(Singleton Pattern):用来创建独一无二的,只能有一个实例的对象的入场券。
单件模式——我要吃巧克力。几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的。您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销。再如大家最经常用的IM,如飞信、QQ,在同一台电脑,一个帐号只能有唯一的登录。穿越时空,我们来到了巧克力制造厂
大家都知道,现代化的巧克力工厂具备计算机控制的巧克力锅炉,锅炉做的事,就是把巧克力和牛奶以及其他原料融在一起,然后送到下一个阶段,一制成美味巧克力。这里有一个Cho-colate 公司的工业强度巧克力锅炉控制器。看看他的代码,你会发现代码写的相当小心,已经用单件模式完美的制作出一炉可口美味的巧克力,当正打包运货的过程中,巧克力锅炉溢出了……原料溢出了
我们来看框中的那一部分代码,假如现在有两个线程A和线程B,当线程A在0.0时刻判断uniqueInstance是否为空(0.0时刻判断巧克力锅是否为空,是空,则想巧克力锅中加入制作原料),也就是线程A执行到this.singletonPattern=newSingletonPattern(),正在申请内存分配,可能在3.0时刻才能new出对象并返回(3.0时刻巧克力棒真正生成,并可以拿着吃了);在2.0时刻之内,线程B执行到if(this.singletonPattern==null),此时的这个判断条件是true还是false? 是true(线程B访问判断时,还是为空,于是再次加入巧克力原料),溢出来了!巧克力原料溢出来了! 在内存中就有两个new出的实例,这样不就存在问题了么。
就这种情况,如何修改,怎么解决,于是引出第一种修改方案:只要把getInstance()变成同步(Synchronized)方法,多线程灾难几乎就可以轻易地解决;
在多个进程访问的时候,必须等第一个进程结束才能依次继续访问,大大地影响运行效率。为了符合大多数java应用程序,很明显地,我们需要确保单件模式能在多线程状况先正常工作。此时第一种修改方案已经不满足需求,我们是否应该想到第二种方案呢?
如果应用程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,我们可能想急切创建此单件,利用这个做法,保证在任县线程访问uniqueInstance静态变量之前,一定先创建此实例。
在Static 静态声明变量,new出的对象一直占存内存,影响内存性能。
利用双重检查加锁,首先检查是否实例已经创建了,如果实例未创建,“才”进行同步,这样一来,只有第一次会同步,这才是我正真想要的。
再度回到巧克力工厂……
此刻,巧克力工厂的问题已经解决了,而且Cho-colate 公司很高兴在锅炉的代码中能够采用这些专业知识。不管你使用哪一种对线程解决方案,锅炉都能顺畅工作,不会有闪失。
标签:
原文地址:http://blog.csdn.net/u010293698/article/details/45391793