单例模式解读:
在应用程序中,保证类型只有一个实例,只允许实例化一次;
步骤:
首先构造函数私有化,以保证对象不会被它人实例化;
提供一个公开的静态方法供他人获取对象的实例;
防止并发情况破坏单例,在创建对象时加锁
第一种方法:
/// <summary> /// 懒汉式单例写法:只有在调用CreateInstance方法后才会实例化Single对象 /// </summary> public sealed class Single { private Single() { long result = 0; for (int i = 0; i < 10000; i++) { result += i; } Thread.Sleep(1000); Console.WriteLine($"{this.GetType().Name}已被构造"); } private static Single single = null;//静态字段在内存中是唯一的,不会被GC private static readonly object SingLock = new object(); public static Single CreateInstance() { //先判断对象是否为null,不为null就不执行里面的代码,直接返回对象 if (single == null) { //加锁:任意时刻只有一个线程能进去,解决并发问题 lock (SingLock) { if (single == null)//这个判断不能去掉,保证只初始化一次 { //方法第一次进来会new一个实例,只会被构造一次 single = new Single(); } } } return single; } public void Message() { Console.WriteLine($"{typeof(Single)}"); } }
static void Main(string[] args) { for (int i = 0; i < 10; i++) { Task.Run(() =>//会抛十个线程 { Single single = Single.CreateInstance(); single.Message(); }); } Console.WriteLine("Hello World!"); Console.ReadKey(); }
第二种:
/// <summary> /// 饿汉式单例写法:在调用类中的任意成员时都会先实例化这个类 /// </summary> public class SingleSecond { private SingleSecond() { long result = 0; for (int i = 0; i < 10000; i++) { result += i; } Thread.Sleep(1000); Console.WriteLine($"{this.GetType().Name}以被构造"); } private static SingleSecond single = null;//静态字段在内存中是唯一的,不会被GC /// <summary> /// 静态构造函数:由CLR保证,在第一次使用到这个类型之前,自动调用且只调用一次 /// </summary> static SingleSecond() { single = new SingleSecond(); } public static SingleSecond CreateInstance() { return single; } public void Message() { Console.WriteLine($"{typeof(SingleSecond)}"); } }
static void Main(string[] args) { for (int i = 0; i < 10; i++) { Task.Run(() =>//会抛十个线程 { SingleSecond single = SingleSecond.CreateInstance(); single.Message(); }); } Console.WriteLine("Hello World!"); Console.ReadKey(); }
第三种:
/// <summary> /// 饿汉式单例写法:在调用类中的任意成员时都会先实例化这个类 /// </summary> public class SingeThird { private SingeThird() { long result = 0; for (int i = 0; i < 10000; i++) { result += i; } Thread.Sleep(1000); Console.WriteLine($"{this.GetType().Name}以被构造"); } /// <summary> /// 静态字段:由CLR保障,在第一次使用这个类型之前,会自动初始化且初始化一次 /// </summary> private static SingeThird single = new SingeThird(); public static SingeThird CreateInstance() { return single; } public void Message() { Console.WriteLine($"{typeof(SingleSecond)}"); } }
static void Main(string[] args) { for (int i = 0; i < 10; i++) { Task.Run(() =>//会抛十个线程 { SingeThird single = SingeThird.CreateInstance(); single.Message(); }); } Console.WriteLine("Hello World!"); Console.ReadKey(); }
单例模式的特点:
同一个实例不能解决多线程并发问题,会存在线程冲突;
全局只有一个单例,对对象里的成员进行修改时,在任何地方调用都是上次修改的值,而不是初始值;
The End!