单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。
在我们平常的开发中,我们需要一些辅助类,比如Redis辅助类,一般把一些初始化的工作放在构造函数中,然后写一些方法来完成Redis要作的一些具体的功能。但是有一个问题,我们每次调用的时候都会去 实例化这个辅助类,然后去调用一些方法。然而每次实例化的时候构造函数里面作的事情都会被重复的做一遍。这与我们预期的并不符合。。。
接下来我们来演示下怎样实现所谓的单例模式。
1.单线程模式下实现单例
public class Singleton { long lResult = 0; private Singleton() { Console.WriteLine("被实例化了一次"); for (int i = 0; i < 100000000; i++) { lResult += i; } } public long GetResult() { return lResult; } private static Singleton _singleton { get; set; } public static Singleton CreateInstance() { if (_singleton == null) { _singleton = new Singleton(); } return _singleton; } }
调用:
for (int i = 0; i < 10; i++) { Singleton singleton = Singleton.CreateInstance(); Console.WriteLine(singleton.GetResult()); }
结果如下:
2.多线程模式下实现单例
我们来将调用的地方修改下:
List<Task> tasks = new List<Task>(); TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < 10; i++) { tasks.Add(taskFactory.StartNew(() => { Singleton singleton = Singleton.CreateInstance(); Console.WriteLine(singleton.GetResult()); })); } Task.WaitAll(tasks.ToArray());
来看看我们将得到结果是什么:
从上面的结果可以看出,第一次只能用于单线程的模式下,多线程下并不行。那么怎样才能让多线程下也可以实现单例呢?
我们只需要修改下辅助类内部即可(用lock来实现)。
修改后的代码:
public class Singleton { private static object singleton_lock = new object(); long lResult = 0; private Singleton() { Console.WriteLine("被实例化了一次"); for (int i = 0; i < 100000000; i++) { lResult += i; } } public long GetResult() { return lResult; } private static Singleton _singleton { get; set; } public static Singleton CreateInstance() { lock (singleton_lock) { if (_singleton == null) { _singleton = new Singleton(); } } return _singleton; } }
结果如下:
上面就实现了我们的多线程下使用单例,当然上面的代码我们还是可以优化下,在lock之前,我们可以再用一个 if (_singleton == null) 来判断一下,至于为什么,自己思考下应该就明白了。
3.使用静态构造函数
辅助类内部代码:
public class SingletonSecond { private static object singletonSecond_lock = new object(); long lResult = 0; private SingletonSecond() { Console.WriteLine("被实例化了一次"); for (int i = 0; i < 100000000; i++) { lResult += i; } } public long GetResult() { return lResult; } private static SingletonSecond _singletonSecond { get; set; } static SingletonSecond() { _singletonSecond = new SingletonSecond(); } public static SingletonSecond CreateInstance() { return _singletonSecond; } }
调用:
List<Task> tasks = new List<Task>(); TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < 10; i++) { tasks.Add(taskFactory.StartNew(() => { SingletonSecond singleton = SingletonSecond.CreateInstance(); Console.WriteLine(singleton.GetResult()); })); } Task.WaitAll(tasks.ToArray());
结果如下:
4.静态对象
内部代码:
public class SingletonThird { private static object singletonSecond_lock = new object(); long lResult = 0; private SingletonThird() { Console.WriteLine("被实例化了一次"); for (int i = 0; i < 100000000; i++) { lResult += i; } } public long GetResult() { return lResult; } private static SingletonThird _singletonThird = new SingletonThird(); public static SingletonThird CreateInstance() { return _singletonThird; } }
调用代码:
List<Task> tasks = new List<Task>(); TaskFactory taskFactory = new TaskFactory(); for (int i = 0; i < 10; i++) { tasks.Add(taskFactory.StartNew(() => { SingletonThird singleton = SingletonThird.CreateInstance(); Console.WriteLine(singleton.GetResult()); })); } Task.WaitAll(tasks.ToArray());
结果如下:
以上三种方式都可以用来实现单例模式。当然还有别的更多的方式,这里只是举一些例子学习用。