多线程系列一
线程,进程,关系我不就不在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 }
输出

多个线程实现了对日志记录处理,并且在空闲时间实现线程暂停,有任务唤醒,以保证,不浪费资源同时能即时处理~!
由于第一次写博客,语言组织能力差,大家就看看程序代码和注释吧!
大家多多指教。
http://www.cnblogs.com/ty408/p/4326195.html


浙公网安备 33010602011771号