1.简介
单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,
可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。
使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
2.实现方式
懒汉式—线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize或lock之类的锁,以提高性能。
懒汉式—线程安全:加上synchronize或lock之类保证线程安全的基础上的懒汉模式,相对性能很低,大部分时间并不需要同步
饿汉方式:指全局的单例实例在类装载时构建。
双检锁式:在懒汉式基础上利用synchronize或lock关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高
登记式:作为创建类的全局属性存在,创建类被装载时创建
枚举:java中枚举类本身也是一种单例模式
3.示例
/// <summary> /// 单例类:一个构造对象很耗时耗资源类型 /// /// 懒汉式单例模式 /// </summary> public class Singleton//<T> //泛型类型里面的静态字段,是随着不同的类型参数唯一的 泛型单例不可能的 { /// <summary> /// 构造函数耗时耗资源 /// </summary> private Singleton()//1 private 避免外部创建 { long lResult = 0; for (int i = 0; i < 10000000; i++) { lResult += i; } Thread.Sleep(1000); Console.WriteLine("{0}被构造一次", this.GetType().Name); } /// <summary> /// 3 全局唯一静态 重用这个变量 /// </summary> private static volatile Singleton _Singleton = null;//volatile 促进线程安全 让线程按顺序操作 private static object Singleton_Lock = new object(); /// <summary> /// 2 公开的静态方法提供对象实例 /// </summary> /// <returns></returns> public static Singleton CreateInstance() { //假如现在 5个线程过来初始化 第1个线程进去把_Singleton实例化;5分钟之后,又有100个线程同时来创建, //排队--判断不为空--然后返回 其实不该排队了,应该直接判断 if (_Singleton == null) { lock (Singleton_Lock)//保证只有一个线程进去判断+初始化 { if (_Singleton == null)//这个也不能去掉,第一次5个线程进来的时候 如果没有这个判断,还是重复创建的 { _Singleton = new Singleton(); } } } return _Singleton; }//懒汉式 调用了方法才去构造 //既然是单例,大家用的是同一个对象,用的是同一个方法,那还会并发吗 还有线程安全问题吗? //当然有,,单例不能解决线程冲突的 解决:加锁 public int iTotal = 0; public void Show() { //lock this.iTotal++; } public static void Test() { } }
/// <summary> /// 单例类:一个构造对象很耗时耗资源类型 /// /// 饿汉式 /// </summary> public class SingletonSecond { /// <summary> /// 1 构造函数耗时耗资源 /// </summary> private SingletonSecond() { long lResult = 0; for (int i = 0; i < 10000000; i++) { lResult += i; } Thread.Sleep(1000); Console.WriteLine("{0}被构造一次", this.GetType().Name); } /// <summary> /// 静态构造函数:由CLR保证,程序第一次使用这个类型前被调用,且只调用一次 /// /// 写日志功能的文件夹检测 /// XML配置文件 /// </summary> static SingletonSecond() { _SingletonSecond = new SingletonSecond(); Console.WriteLine("SingletonSecond 被启动"); } private static SingletonSecond _SingletonSecond = null; public static SingletonSecond CreateInstance() { return _SingletonSecond; }//饿汉式 只要使用类就会被构造 public static void Test() { } public int iTotal = 0; public void Show() { this.iTotal++; } }
/// <summary> /// 单例类:一个构造对象很耗时耗资源类型 /// 饿汉式 /// </summary> public class SingletonThird { /// <summary> /// 构造函数耗时耗资源 /// </summary> private SingletonThird() { long lResult = 0; for (int i = 0; i < 10000000; i++) { lResult += i; } Thread.Sleep(1000); Console.WriteLine("{0}被构造一次", this.GetType().Name); } /// <summary> /// 静态字段:在第一次使用这个类之前,由CLR保证,初始化且只初始化一次 /// 这个比今天构造函数还早 /// </summary> private static SingletonThird _SingletonThird = new SingletonThird();//打印个日志 public static SingletonThird CreateInstance() { return _SingletonThird; }//饿汉式 只要使用类就会被构造 public void Show() { Console.WriteLine("这里是{0}.Show", this.GetType().Name); } }