• 设计模式系列:单例模式(Singleton Pattern)


    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);
            }
    
        }
  • 相关阅读:
    ms日期函数大全
    Sql server char,nchar,varchar与Nvarchar的区别
    clientX pageX
    jswindow对象的方法和属性资料
    Asp.Net中不修改IIS实现URL重写,支持任意扩展名及无扩展名
    该行已经属于另一个表的解决方法
    dopostBack机制(转)
    js触发asp.net的Button的Onclick事件
    Value、ReadString、ReadContentAsString、ReadElementContentAsString 区别
    有关元素元素位置的属性
  • 原文地址:https://www.cnblogs.com/vic-tory/p/12147337.html
Copyright © 2020-2023  润新知