多線程系列(三)之線程池

什麼是線程池?

.NetFramework1.0時代的Thread,API功能繁多,對線程的數量是沒有管控的,在.NetFramework2.0時代推出了ThreadPool,若是某個對象建立和銷燬代價比較高,同時這個對象還能夠反覆使這些線程,就須要使用線程池,線程池能夠保存多個線程對象,須要使用線程時直接從線程池裏面拿,使用完以後不作釋放,又放回池子(享元模式),須要用的時候再去拿。這樣能夠減小建立線程的開銷,提高性能,此外,還能夠管控線程的總數量,防止資源濫用。數組

委託異步調用、Task、Parrallel、async/await的線程所有都是線程池裏面的線程。直接new Thread開起的線程不受線程池的數量限制(可是會佔用線程池的線程數量)。異步

使用線程池開啓線程

            ThreadPool.QueueUserWorkItem(o=>this.DoSomeThing("btnThreadPool_Click_1"));
            ThreadPool.QueueUserWorkItem(o => {
                this.DoSomeThing("btnThreadPool_Click_2");
                Console.WriteLine( o?.ToString());
            }, "wjl");

檢索和設置線程池的最大最小數目和異步IO線程的最大最小數目

I/O線程是.NET專爲訪問外部資源所設置的一種線程,由於訪問外部資源經常要受到外界因素的影響,爲了防止讓主線程受影響而長期處於阻塞狀態,.NET爲多個I/O操做都創建起了異步方法。async

            //檢索由 GetMaxThreads 返回的線程池線程的最大數目和異步IO線程的最大數目
            ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
            Console.WriteLine($"當前線程池最大數目爲:{workerThreads},最大異步IO線程:{completionPortThreads}");

            //檢索由 GetMinThreads 返回的線程池線程的最小數目和異步IO線程的最小數目
            ThreadPool.GetMinThreads(out int workerThreadsMin, out int completionPortThreadsMin);
            Console.WriteLine($"當前線程池最小數目爲:{workerThreadsMin},最小異步IO線程:{completionPortThreadsMin}");

            ThreadPool.SetMaxThreads(8, 8);//設置的最大值,必須大於CPU核數,不然設置無效
            ThreadPool.SetMinThreads(2, 2);

線程等待

單個線程等待:函數

                //線程等待
                ManualResetEvent mre = new ManualResetEvent(false);
                //ManualResetEvent是一種信號量的方式
                //若是初始爲false--關閉, mre.Set()以後變爲ture,WaitOne就能經過
                //若是初始爲tue--打開, mre.Rset()以後變爲false,WaitOne就只能等待
                ThreadPool.QueueUserWorkItem(o => {
                    this.DoSomeThing("btnThreadPool_Click_3");
                    mre.Set();
                });
                mre.WaitOne();
                Console.WriteLine("任務已經完成了...");

多個線程等待:性能

                ManualResetEvent[] mres = new ManualResetEvent[10];
                for (int i = 0; i < 10; i++)
                {
                    mres[i] = new ManualResetEvent(false);
                    int k = i;
                    ThreadPool.QueueUserWorkItem(o =>
                    {
                        this.DoSomeThing($"mres{k}");
                        ManualResetEvent mre = o as ManualResetEvent;
                        mre.Set();
                    }, mres[i]);
                }
                //等待全部數組中的元素都收到信號,若是是控制檯程序或者winform程序,請將Main()函數上面的特性[STAThread]註釋掉
                WaitHandle.WaitAll(mres);
                Console.WriteLine("多個任務已經完成了...");
相關文章
相關標籤/搜索