【软件编程】Singleton单例模式

-----------设计模式之 单例模式---------------

 单例模式是创建模式中普遍采用的一种。使用单例模式可以确保某个类只会有一个实例被创建。

 

它的特点:
     变量=私有+静态
     构造函数=私有
     方法=公有+静态

        Java 语言中单例模式的一个最重要的特点是类的构造器是私有的。从而避免外界利用构造器直接创建出任意多的实例。
        通俗的说,就是外部类不能随便就new一个单例类的对象了,因为构造器私有,受权限限制。
值得指出的是,由于构造器是私有的,因此,此类不能被继承。

两种形式:

饿汉式:

在类加载到内存时就初始化实例了。
推荐使用它的原因:
    1.是线程安全的,
    2.在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变 。

懒汉式:

在类第一次被引用时将自己实例化。话句话就是,第一次调用该单子类方法的时候被初始化。
    1.如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。
    2.synchronized的重要性
       如果在多线程的环境,程序可能会有两个甚至两个以上的singleton对象被创建出来,从而造成错误。为了克服没有线程安全的缺点,我们使用synchronized。同步化实际上只在singleton对象第一次被赋值之前才有用。
在singleton对象有了值以后,同步化实际上变成了一个不必要的瓶颈。于是就有了双重检查成例。(见代码@改进版懒汉式)

       因为java不支持双重检查成例,由于 Java 内存模型的一些细节的原因,会出问题。专家建议不要使用此版本。
       详情:登录IBM-中国,网站地址:http://www.ibm.com/developerworks/cn/java/j-dcl.html

优点:

           从速度和反应时间角度来讲,饿汉式好。
         从资源利用效率上说,懒汉式好。

         一些资深专家建议使用饿汉式,如果非要使用懒汉式,就用原始版的懒汉式。

补充:

一些资源管理器常常设计成单例模式。
        当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费时间。 这意味着出现多线程同时首次引用此类的机率变得较大。
        比方说,(如果想使用懒汉式的话)线程1首次引用此类,初始化还未结束,时间片就分给了线程2,可能由于优先级的原因。线程2占用时间挺长,把类初始化结束了,singleton对象有了值,这时,线程1开始工作了,那么此时它的singleton对象变量是null还是线程2的值呢。会造成系统异常。必须处理好在多个线程同时首次引用此类时的访问限制问题。

 

 1 package mode;
 2 
 3 //单例模式
 4 public class Singleton 
 5 {
 6     public static void main(String[] args)
 7     {
 8         SingTest st=SingTest.getInstance();
 9         System.out.println(st);
10     }
11 }
12 
13 
14 /**
15  * ----------------专家推荐饿汉式-------------------
16  */
17 
18 
19 class SingTest
20 {
21     private static SingTest instance = new SingTest(); 
22     private SingTest(){}
23     public static SingTest getInstance()
24     {
25         return instance;
26     }
27 }
28 
29 
30 
31 /*--------------原始版懒汉式--------------------*/
32 
33 /*class SingTest
34 {
35     private static SingTest instance = null; 
36     private SingTest(){}
37     public static synchronized SingTest getInstance()
38     {
39         if(instance==null)
40         {
41             instance=new SingTest();
42         }
43         return instance;
44     }
45 }*/
46 
47 
48 /**
49  *  --------------改进版懒汉式-----------------------
50  */
51 
52 /*
53  * 此版虽然改进了同步化处理的小瓶颈问题。但是java不支持双重检测成例。
54    在执行下面代码时,由于一些不太常见的 Java 内存模型细节的原因,并不能保证这个双重检查锁定习语有效。
55    它偶尔会失败,而不是总失败。此外,它失败的原因并不明显,还包含 Java 内存模型的一些隐秘细节。
56    这些事实将导致代码失败,原因是双重检查锁定难于跟踪。
57 */
58 /*class SingTest
59 {
60     private static SingTest instance = null; 
61     private SingTest(){}
62     public static SingTest getInstance()
63     {
64         if(instance==null)
65         {
66             synchronized(SingTest.class)
67             {
68                 if(instance==null)
69                 {
70                     instance=new SingTest();
71                 }
72             }
73         }
74         return instance;
75     }
76 }*/
77 
78 
79 
80 
posted @ 2008-10-04 23:29  蒋琦  阅读(379)  评论(0编辑  收藏  举报