多线程系列一

线程,进程,关系我不就不在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     }

输出

多线程系列一

多个线程实现了对日志记录处理,并且在空闲时间实现线程暂停,有任务唤醒,以保证,不浪费资源同时能即时处理~!

由于第一次写博客,语言组织能力差,大家就看看程序代码和注释吧!

大家多多指教。

 

你可能感兴趣的:(多线程)