C#--設計模式--單例模式【三種方式】

 1.單線程單例:

/// <summary>
    /// 單例模式
    /// 1.單線程單例
    /// 2.多線程單例--lock
    /// 單例是在程序運行時,初始化對象內存,將會常駐內存,
    /// 後期不會再實例化。保證內存唯一隻初始化一次
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            ///單線程單例模式
            SingleInit1();
            ///多線程
            TaskInit();
            Console.ReadKey();
        }

        
        private static void TaskInit()
        {
            for (int i = 0; i < 10; i++)
            {
                Task task = new Task(() => {
                    SingleClass single = SingleClass.CreateSingleClass();
                    single.ShowText();
                });
                task.Start();
            }
            
        }

        /// <summary>
        /// 單線程單例
        /// </summary>
        private static void SingleInit1()
        {
            
            for (int i = 0; i < 10; i++)
            {
                SingleClass single = SingleClass.CreateSingleClass();
                single.ShowText();
            }
        }
    }

singleClass類

class SingleClass
    {
        private static SingleClass singleObject = null;
        private SingleClass()
        {
            Thread.Sleep(5000);
            Console.WriteLine("當前實例對象:{0},當前線程ID:{1}", this.GetType(), Thread.CurrentThread.ManagedThreadId);
        }
        public static SingleClass CreateSingleClass()
        {
            if (singleObject == null)
            {
                singleObject = new SingleClass();
            }
            return singleObject;
        }

        public void ShowText()
        {
            Console.WriteLine("調用顯示方法");
        }
    }

演示結果:
singleInit()方法執行結果在單線程的情況下,內存中只會實例化一次SingleClass,顯示結果如下:

TaskInit()方法執行,在多線程情況下,然而並不能保證實例化一次,顯示結果如下:

由此,可見在多線程情況下,並沒有保證SingleClass只實例化一次,如是改進如下:

static void Main(string[] args)
        {
            ///單線程單例模式
            //SingleInit1();
            ///多線程
            //TaskInit();

            ///多線程-單例
            TaskSingleInit();
            Console.ReadKey();
        }

        private static void TaskSingleInit()
        {
            for (int i = 0; i < 10; i++)
            {
                Task task = new Task(() =>
                {
                    TaskSingleClass taskSingle = TaskSingleClass.CreateTaskSingleClass();
                    taskSingle.ShowText();
                });
                task.Start();
               
            }
            
        }

TaskSingleClass對象

class TaskSingleClass
    {
        private static TaskSingleClass taskSingleClass = null;//實例化TaskSingleClass對象變量
        private static Object lockObject = new Object(); //初始化Object,用於lock
        private TaskSingleClass()
        {
            Thread.Sleep(1000);
            Console.WriteLine("當前對象{0},線程Id{1}",this.GetType(),Thread.CurrentThread.ManagedThreadId);
        }

        public static TaskSingleClass CreateTaskSingleClass()
        {
            if (taskSingleClass == null)//在lock等待之前判斷是否實例化,如果實例化直接返回。提升性能
            {
                lock (lockObject)
                {
                    if (taskSingleClass == null)
                    {
                        taskSingleClass = new TaskSingleClass();
                    }
                }
            }
            return taskSingleClass;

        }
        public void ShowText()
        {
            Console.WriteLine("方法調用");
        }

    }

TaskSingleClass類中對多線程進行了處理,在多個線程的情況下,保證了TaskSingleCalss只被實例化一次,運行結果如下:
靜態構造函數初始化(簡單)
 

 public class StaticSingleClass
    {
        private static StaticSingleClass staticSingle = null;
        private StaticSingleClass()
        {
            Console.WriteLine("構造函數");
            Thread.Sleep(1000);
            Console.WriteLine("當前對象{0},線程Id{1}", this.GetType(), Thread.CurrentThread.ManagedThreadId);
        }


        /// <summary>
        /// 方式1 靜態構造函數
        /// </summary>
        static StaticSingleClass()
        {
            Console.WriteLine("靜態構造函數,在構造函數之前執行");//並且只執行一次,由CLR調用執行,並且只執行一次
            staticSingle = new StaticSingleClass();
        }
        /// <summary>
        /// 方式2 靜態變量
        /// </summary>
        /// <returns></returns>
        static StaticSingleClass singleStatic = new StaticSingleClass();

        public static StaticSingleClass CreateSingleInit()
        {
            return staticSingle;
        }

        public void ShowText()
        {
            Console.WriteLine("調用方法");
        }

    }

StaticSingleClass對象中,並沒有添加Lock,來處理多線程情況,而是使用static 構造函數和靜態變量來處理多線程單例模式,是因爲static代碼塊和static變量,是由CLR在使用之前調用,並且只調用了一次。所有也能夠保證唯一性;
結果如下:

註明:上面是參考其他文檔,如果設計到版權問題,麻煩聯繫。謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章