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

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