• Singleton


    单例模式:保证进程中,某个类只有一个实例。

    要做到单例,必须要解决一下几个问题:

    1 怎么保证呢?怎么样强制保证呢?

    单例模式的三部曲:A.构造方法私有化,防止外部对它实例化。B. 静态对象、方法的申明。C.判断对象是否为空,为空则创建对象,最后返回对象。

    示例代码:

     1 /// <summary>
     2     /// 单例类:一个构造对象很耗时耗资源类型
     3     /// 懒汉式单例模式
     4     /// </summary>
     5     public class Singleton
     6     {
     7         /// <summary>
     8         /// 构造函数耗时耗资源
     9         /// </summary>
    10         private Singleton()
    11         {
    12             18             Console.WriteLine("{0}被构造一次", this.GetType().Name);
    19         }
    20         /// <summary>
    21         /// 3 全局唯一静态  重用这个变量
    22         /// </summary>
    23         private static volatile Singleton _Singleton = null;
    24         //volatile 促进线程安全 让线程按顺序操作
    25         private static readonly object Singleton_Lock = new object();
    26         /// <summary>
    27         /// 2 公开的静态方法提供对象实例
    28         /// </summary>
    29         /// <returns></returns>
    30         public static Singleton CreateInstance()
    31         {
    40             if (_Singleton == null)//保证只实例化一次
    41            {
    42             _Singleton = new Singleton();
    43            }46             return _Singleton;
    47         }
    65     }

    调用:Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));  控制台输出ture,则说明这个两个对象是同一个对象。

     1  static void Main(string[] args)
     2         {
     3             try
     4             {
     5                 //为什么要有单例设计模式?
     6                 //构造对象耗时耗资源,很多地方都需要去new, 这个方法 其他方法  其他类
     7                 //想避免重复构造,公开静态字段 
     8                 //1 提前构造  2 没办法保证都是用这个(其他人还是new了一下) 
     9                 //Singleton singleton = new Singleton();
    10                 //singleton.Show();
    11 
    12                 //{
    13                 //    ////保证进程中,某个类只有一个实例
    14                 //    ////1 构造函数私有化 避免别人还去new
    15                 //    ////2 公开的静态方法提供对象实例
    16                 //    ////3 初始化一个静态字段用于返回 保证全局都是这一个
    17                  Singleton singleton1 = Singleton.CreateInstance();
    18                  Singleton singleton2 = Singleton.CreateInstance();
    19                  Singleton singleton3 = Singleton.CreateInstance();
    20                       Console.WriteLine(object.ReferenceEquals(singleton1, singleton2));
    21                       Console.WriteLine(object.ReferenceEquals(singleton3, singleton2));
    22                  }
    23             catch (Exception ex)
    24             {
    25                 Console.WriteLine(ex.Message);
    26             }
    27             Console.Read();
    28         }

    多线程调用:控制台输出 对象被构造了五次,这时候就会发现结果和我们预期的不一样了。

    {
           for (int i = 0; i < 5; i++)
           {
              Task.Run(() =>//启动线程完成--5个线程并发执行,同时去执行这个方法
               {
                Singleton singleton1 = Singleton.CreateInstance();
                 singleton1.Show();
               });
    } }

    对上述单例模式进行改造,要求是满足多线程使用场景、单线程使用场景。

     1 /// <summary>
     2     /// 单例类:一个构造对象很耗时耗资源类型
     3     /// 懒汉式单例模式
     4     /// </summary>
     5     public class Singleton
     6     {
     7         /// <summary>
     8         /// 构造函数耗时耗资源
     9         /// </summary>
    10         private Singleton()
    11         {
    12             long lResult = 0;
    13             for (int i = 0; i < 10000000; i++)
    14             {
    15                 lResult += i;
    16             }
    17             Thread.Sleep(2000);
    18             Console.WriteLine("{0}被构造一次", this.GetType().Name);
    19         }
    20         /// <summary>
    21         /// 3 全局唯一静态  重用这个变量
    22         /// </summary>
    23         private static volatile Singleton _Singleton = null;
    24         //volatile 促进线程安全 让线程按顺序操作
    25         private static readonly object Singleton_Lock = new object();
    26         /// <summary>
    27         /// 2 公开的静态方法提供对象实例
    28         /// </summary>
    29         /// <returns></returns>
    30         public static Singleton CreateInstance()
    31         {
    32             if (_Singleton == null)//是_Singleton已经被初始化之后,就不要进入锁等待了
    33             {
    34                 lock (Singleton_Lock)
    35                 //保证任意时刻只有一个线程进入lock范围
    36                 //也限制了并发,尤其是_Singleton已经被初始化之后
    37                 {
    38                     //Thread.Sleep(1000);
    39                     //Console.WriteLine("等待锁1s之后才继续。。。");
    40                     if (_Singleton == null)//保证只实例化一次
    41                     {
    42                         _Singleton = new Singleton();
    43                     }
    44                 }
    45             }
    46             return _Singleton;
    47         }
    48 
    49         //既然是单例,大家用的是同一个对象,用的是同一个方法,那还会并发吗  还有线程安全问题吗?
    50         public int iTotal = 0;
    51         public void Show()
    52         {
    53             //lock (Singleton_Lock)
    54             //{
    55                 this.iTotal++;
    56             //}
    57         }
    58 
    59         public static void Test()
    60         {
    61             Console.WriteLine("Test1");
    62             Console.WriteLine(_Singleton.iTotal);
    63         }
    64 
    65     }

    多线程调用: 

     Thread.Sleep(10000);
      Console.WriteLine("第一波多线程后,再度来请求实例");
         for (int i = 0; i < 5; i++)
         {
               Task.Run(() =>//启动线程完成--5个线程并发执行,同时去执行这个方法
               {
                   Singleton singleton1 = Singleton.CreateInstance();
                   singleton1.Show();
                });
         }

    注意:多线程中单例的使用 最主要的是 双重if判断,和加锁。内层if判断的作用是第一次调用实例化一次,下次在调用的时候不用实例化对象。加锁的作用说保证线程安全(加锁后就变成的单线程,第一个线程没有处理完,后面的线程都需要等待,这个时候就使用多线程就失去了意义),为了解决加锁后编程单线程问题,所以在锁外面在加一层If判断,多线程操作程序会并发执行,当第一个线程已经创建了对象 ,其他线程进入方法是检测到对象已经不为空后,直接返回对象。这样就不用等待,提高了程序的效率。

    饿汉式单例

      

     1 /// <summary>
     2     /// 单例类:一个构造对象很耗时耗资源类型
     3     /// 
     4     /// 饿汉式
     5     /// </summary>
     6     public class SingletonSecond
     7     {
     8         /// <summary>
     9         /// 1 构造函数耗时耗资源
    10         /// </summary>
    11         private SingletonSecond()
    12         {
    13             long lResult = 0;
    14             for (int i = 0; i < 10000000; i++)
    15             {
    16                 lResult += i;
    17             }
    18             Thread.Sleep(1000);
    19             Console.WriteLine("{0}被构造一次", this.GetType().Name);
    20         }
    21         /// <summary>
    22         /// 静态构造函数:由CLR保证,程序第一次使用这个类型前被调用,且只调用一次
    23         /// 
    24         /// 检测,初始化
    25         /// 写日志功能的文件夹检测
    26         /// XML配置文件
    27         /// </summary>
    28         static SingletonSecond()
    29         {
    30             _SingletonSecond = new SingletonSecond();
    31             Console.WriteLine("SingletonSecond 被启动");
    32         }
    33 
    34 
    35         private static SingletonSecond _SingletonSecond = null;
    36         public static SingletonSecond CreateInstance()
    37         {
    38             return _SingletonSecond;
    39         }//饿汉式  只要使用类就会被构造
    40 
    41         /// <summary>
    42         /// 原型模式:解决对象重复创建的问题
    43         /// 通过MemberwiseClone来clone新对象,内存操作,直接复制的,避免重复创建
    44         /// </summary>
    45         /// <returns></returns>
    46         public static SingletonSecond CreateInstancePrototype()
    47         {
    48             SingletonSecond second = (SingletonSecond)_SingletonSecond.MemberwiseClone();
    49             return second;
    50         }
    51 
    52         public static void Test()
    53         {
    54             Console.WriteLine("Test2");
    55         }
    56 
    57 
    58 
    59         public int iTotal = 0;
    60         public void Show()
    61         {
    62             this.iTotal++;
    63         }
    64 
    65     }

    第三种单例模式 :

     1 /// <summary>
     2     /// 单例类:一个构造对象很耗时耗资源类型
     3     /// 饿汉式
     4     /// </summary>
     5     public class SingletonThird
     6     {
     7         /// <summary>
     8         /// 构造函数耗时耗资源
     9         /// </summary>
    10         private SingletonThird()
    11         {
    12             long lResult = 0;
    13             for (int i = 0; i < 10000000; i++)
    14             {
    15                 lResult += i;
    16             }
    17             Thread.Sleep(1000);
    18             Console.WriteLine("{0}被构造一次", this.GetType().Name);
    19         }
    20 
    21         /// <summary>
    22         /// 静态字段:在第一次使用这个类之前,由CLR保证,初始化且只初始化一次
    23         /// 这个比今天构造函数还早
    24         /// </summary>
    25         private static SingletonThird _SingletonThird = new SingletonThird();//打印个日志
    26         public static SingletonThird CreateInstance()
    27         {
    28             return _SingletonThird;
    29         }//饿汉式  只要使用类就会被构造

    34 public void Show() 35 { 36 Console.WriteLine("这里是{0}.Show", this.GetType().Name); 37 } 38 39 }

    辅导费

  • 相关阅读:
    Ubuntu – vlan & bridge configuration
    Python 腾讯云宝塔面板 B站获取经验脚本 部署 自动发邮件
    struts1的总结
    在oracle 中自己所做的作业。。
    昨天上课学到的东西
    今天关于一些学习了国际化的知识
    学习的第二个框架hibernate
    我学习struts的一些心得!
    hibernate的几种状态的详解
    关于hibernate的,另外一些应用!
  • 原文地址:https://www.cnblogs.com/super-xi-xi/p/10308588.html
Copyright © 2020-2023  润新知