国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

多線程系列一

2019-11-17 02:32:20
字體:
來源:轉載
供稿:網友

多線程系列一

線程,進程,關系我不就不在BB了。

關于線程,其實我相信大家都了解了很多,此處我只是發表我對線程的理解和認識,不喜勿噴。如有不對之處還請大家指出。

 1     class PRogram 2     { 3         static void Main(string[] args) 4         { 5             Thread t = new Thread(Runing); 6             t.Name = "測試線程"; 7             t.Start(); 8             Console.ReadLine(); 9         }10 11         static void Runing()12         {13             Console.WriteLine(Thread.CurrentThread.Name + " :" + DateTime.Now.ToString());14         }15     }

上述代碼大家肯定都不陌生~!

接下來我們修改一下程序,完成單線程處理任務。我們知道很多時候,當我們的程序設計,又多個客戶端或者稱多個請求來源,并發請求來了以后,我們需要按照隊列處理事情比如秒殺下單

public class MyThread1    {        //通知一個或多個正在等待的線程已發生事件        ManualResetEvent mre = new ManualResetEvent(false);        //服務器的運行標識        bool isRuning = true;        //線程安全的隊列        System.Collections.Concurrent.ConcurrentQueue<string> cqueue = new System.Collections.Concurrent.ConcurrentQueue<string>();        public MyThread1()        {            Thread t = new Thread(RunTest);            t.Name = "我是測試線程";            t.Start();        }        //模擬新增任務        public void add(int i)        {            //添加任務到隊列            cqueue.Enqueue("" + i);            //喚醒所有相關的掛起線程            mre.Set();        }        static void Main(string[] args)        {            MyThread1 p = new MyThread1();            for (int i = 0; i < 10; i++)            {                p.add(i);            }            Console.ReadLine();        }        void RunTest()        {            //主循環 服務器運行標識            while (isRuning)            {                //如果是空則繼續等待      服務器運行標識                while (cqueue.IsEmpty && isRuning)                {                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + "  sleep");                    //重置線程暫停狀態                    mre.Reset();                    //這個操作是以便服務器需要停止操作,                    //如果停止調用線程的Thread.Abort()是會導致處理隊列任務丟失                    mre.WaitOne(2000);                }                string ret;                //取出隊列任務                if (cqueue.TryDequeue(out ret))                {                    //測試輸出任務                    Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + "  " + ret);                }            }        }    }

通過add實現并發下單 RunTest() 方法來實現處理邏輯,

此處通過 ManualResetEvent 實現對線程的掛起和喚醒操作。當隊列為空的時候,線程自動進入掛起狀態,當有新的任務,add操作的時候直接喚醒掛起的線程。立即進入處理狀態。

為什么選用 ManualResetEvent 這個線程通知這里就不在解釋了有興趣的可以自己百度~!

為了避免在需要關閉服務器的時候調用線程的Thread.Abort() 導致后續隊列操作失效,所以加入了isRuning的bool變量實現線程是否繼續運行。

上述功能僅僅是永遠類似于處理下單,需要單線程隊列處理情況。各位看官請自行分析需求~~!

有了上述單線程處理隊列需求,我們也許會想到那么在程序運行中自然有多線程處理隊列。

比如我們記錄日志的情況,(打個比方而已如果你很喜歡log4Net or log4J 請繞道) 我們需要提交日志記錄,但是不想這個操作耽誤程序的正常運行,且想日志這樣的記錄程序肯定不能單一線程處理,

如果日志瘋狂記錄,那么勢必會導致處理不及時內存暴漲溢出問題

于是再次修改一下程序

 1 public class MyThread3 2     { 3         //通知一個或多個正在等待的線程已發生事件 4         ManualResetEvent mre = new ManualResetEvent(false); 5         //服務器的運行標識 6         bool isRuning = true; 7         //線程安全的隊列 8         System.Collections.Concurrent.ConcurrentQueue<string> cqueue = new System.Collections.Concurrent.ConcurrentQueue<string>(); 9         //計數存儲器10         Dictionary<string, int> cdic = new Dictionary<string, int>();11 12         public MyThread3()13         {14             List<Thread> ts = new List<Thread>();15             for (int i = 0; i < 4; i++)16             {17                 Thread t = new Thread(RunTest);18                 t.Name = "我是線程(" + i + ")";19                 cdic[t.Name] = 0;20                 t.Start();21                 ts.Add(t);22             }23         }24 25         //模擬新增任務26         public void Add()27         {28             Thread t1 = new Thread(() =>29             {30                 for (int i = 0; i < 40; i++)31                 {32                     //添加任務到隊列33                     cqueue.Enqueue("日志記錄 " + i);34                     //喚醒所有相關的掛起線程35                     mre.Set();36                 }37 38             });39             t1.Start();40 41         }42 43         //輸出計數器44         public override string ToString()45         {46             foreach (var item in cdic)47             {48                 Console.WriteLine(item.Key + " 計數 " + item.Value);49             }50             return "";51         }52 53 54         static void Main(string[] args)55         {56             MyThread3 p = new MyThread3();57             p.Add();58             Console.ReadLine();59             p.ToString();60             Console.WriteLine();61             Console.ReadLine();62         }63 64         void RunTest()65         {66             //主循環 服務器運行標識67             while (isRuning)68             {69                 //如果是空則繼續等待      服務器運行標識70                 while (cqueue.IsEmpty && isRuning)71                 {72                     //重置線程暫停狀態73                     mre.Reset();74                     //這個操作是以便服務器需要停止操作,75                     //如果停止調用線程的Thread.Abort()是會導致處理隊列任務丟失76                     mre.WaitOne(2000);77                     Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + "  sleep");78                 }79                 string ret;80                 //取出隊列任務81                 if (cqueue.TryDequeue(out ret))82                 {83                     //測試輸出任務84                     Console.WriteLine(DateTime.Now.ToString("HH:mm:ss:ffff") + " : " + Thread.CurrentThread.Name + "  " + ret);85                     //添加任務的計數器,為了查看最后線程執行任務的計數86                     cdic[Thread.CurrentThread.Name] = cdic[Thread.CurrentThread.Name] + 1;87                 }88             }89         }90     }

輸出

多個線程實現了對日志記錄處理,并且在空閑時間實現線程暫停,有任務喚醒,以保證,不浪費資源同時能即時處理~!

由于第一次寫博客,語言組織能力差,大家就看看程序代碼和注釋吧!

大家多多指教。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 吉林市| 天峻县| 玉环县| 五莲县| 婺源县| 崇明县| 安庆市| 明光市| 德惠市| 天台县| 竹溪县| 神木县| 保德县| 襄垣县| 黑龙江省| 嵩明县| 伊川县| 易门县| 隆德县| 连山| 宜宾市| 桐城市| 丰都县| 新密市| 深水埗区| 陆川县| 司法| 泰兴市| 珲春市| 台北县| 达孜县| 合水县| 宁蒗| 寻乌县| 马龙县| 石狮市| 峨眉山市| 准格尔旗| 景宁| 大石桥市| 旬邑县|