10-单例模式

1. 单例模式的作用

    保证多个进程内,(即使多线程访问)该对象的实例只有一个,而且只会被创建一次。

2. 单例模式什么时候用?

     该对象的构造函数非常耗时,实例化一次该对象,需要非常长的时间,这样如果每次都去创建,会消耗很多资源。

3. 单例模式的代价

    private static Singleton _Singleton = null;  该静态对象不会被回收,会常驻内存。

4. 特别注意

   单例只保证了实例的唯一,并不能保证实例中的方法或变量也唯一,所以单例中的方法或变量,在多线程面前,仍然可能是不安全的。

5. 单例模式的三种写法

   双if+Lock(懒汉模式)、静态构造函数(饿汉模式)、静态变量(饿汉模式)。

   (1). 双if+Lock

   下面重点介绍“双if+Lock”由单线程→多线程的演变过程。

 1  public class SOne
 2     {
 3         /// <summary>
 4         /// 模拟耗时的构造函数
 5         /// </summary>
 6         public SOne()
 7         {
 8             long result = 0;
 9             for (int i = 0; i < 1000000; i++)
10             {
11                 result += i;
12             }
13             Thread.Sleep(1000);
14             Console.WriteLine("{0}被构造...", this.GetType().Name);
15         }
16 
17         private static SOne _Sone = null;
18         private static object SoneLock = new object();
19 
20         /// <summary>
21         /// 单线程内单例模式
22         /// </summary>
23         /// <returns></returns>
24         public static SOne CreateIntance1()
25         {
26             //我们发现:在多线程中,实例创建了不止一次,原因是多个线程同时进入了
27             if (_Sone == null)
28             {
29                 _Sone = new SOne();
30             }
31             return _Sone;
32         }
33         /// <summary>
34         /// 多线程的单例模式(安全+但是费时,费在锁上了)
35         /// </summary>
36         /// <returns></returns>
37         public static SOne CreateIntance2()
38         {
39             //给下面的语句整体加上锁,即使多线程,也需要一个一个的进入锁中进行判断,不存在同时进入创建实例内部的情况了。
40             //缺点:同时带来一个问题,所有的线程必须等着前面一个锁完成后,方可进入,即使实例已经创建完了,也需要等前面的锁完成,这样多个线程耗时就耗在等锁上了
41             lock (SoneLock)
42             {
43                 Console.WriteLine("我进入锁了,后面的要等我一下哦");
44                 Thread.Sleep(1000); //模拟锁操作耗时
45                 if (_Sone == null)
46                 {
47                     _Sone = new SOne();
48                 }
49             }
50             return _Sone;
51         }
52 
53         /// <summary>
54         /// 多线程的单例模式(安全且不耗时)
55         /// </summary>
56         /// <returns></returns>
57         public static SOne CreateIntance3()
58         {
59             //外层再加一层if,在进锁前就可以判断了,如果前面已经有实例创建好了,那么以后的就不需要等锁了,但是也可能存在多线程同时进入第一个if,那么同时进入的也要等一下哦。
60             if (_Sone==null)
61             {
62                 lock (SoneLock)
63                 {
64                     Console.WriteLine("我进入锁了,后面的要等我一下哦");
65                     //Thread.Sleep(1000); //模拟锁操作耗时
66                     if (_Sone == null)
67                     {
68                         _Sone = new SOne();
69                     }
70                 }
71             }      
72             return _Sone;
73         }
74     }

   (2). 静态构造函数

 1    public class STwo
 2     {
 3         /// <summary>
 4         /// 模拟耗时的构造函数
 5         /// </summary>
 6         private STwo()
 7         {
 8             long result = 0;
 9             for (int i = 0; i < 1000000; i++)
10             {
11                 result += i;
12             }
13             Thread.Sleep(1000);
14             Console.WriteLine("{0}被构造...", this.GetType().Name);
15         }
16 
17         private static STwo _STwo = null;
18         /// <summary>
19         /// 静态的构造函数:只能有一个,且是无参数的
20         /// 由CLR保证,只有在程序第一次使用该类之前被调用,而且只能调用一次
21         /// </summary>
22         static STwo()
23         {
24             _STwo = new STwo();
25         }
26 
27         public static STwo CreateIntance()
28         {
29             return _STwo;
30         }
31     }

   (3). 静态变量

 1  public  class SThird
 2     {
 3         /// <summary>
 4         /// 模拟耗时的构造函数
 5         /// </summary>
 6         private SThird()
 7         {
 8             long result = 0;
 9             for (int i = 0; i < 1000000; i++)
10             {
11                 result += i;
12             }
13             Thread.Sleep(1000);
14             Console.WriteLine("{0}被构造...", this.GetType().Name);
15         }
16         /// <summary>
17         /// 静态变量:由CLR保证,在程序第一次使用该类之前被调用,而且只调用一次
18         /// </summary>
19         private static SThird _SThird = new SThird();
20 
21         public static SThird CreateIntance()
22         {
23             return _SThird;
24         }
25     }

 

posted @ 2017-07-08 22:57  Yaopengfei  阅读(417)  评论(0编辑  收藏  举报