線程,進程,關系我不就不在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 }輸出

多個線程實現了對日志記錄處理,并且在空閑時間實現線程暫停,有任務喚醒,以保證,不浪費資源同時能即時處理~!
由于第一次寫博客,語言組織能力差,大家就看看程序代碼和注釋吧!
大家多多指教。
新聞熱點
疑難解答