首页 > 代码库 > c#自己实现线程池功能(二)

c#自己实现线程池功能(二)

介绍

在上一篇c#自己实现线程池功能(一)中,我们基本实现了一个能够执行的程序。而不能真正的称作线程池。因为是上篇中的代码有个致命的bug那就是没有任务是并非等待,而是疯狂的进行while循环,并试图lock任务链表,这样带来的问题的就是性能相当低下,程序反映速度非常慢(当增加一个新任务后,要过非常久这个job才開始执行)造成的原因就是刚才所说的。

为了解决问题我们就须要使用某种方法使得程序可以让进程同步。

方法一

使用信号量

我们为了降低对task任务的加锁操作,仅仅有当task不为空时才进行试探。

我们的信号量就代表的是任务表里面的数量。当s.WaitOne();成功后我们才開始加锁,并取出任务

while (flag && TaskQueue != null)
            {
                //等待任务
                ThreadPoolManager.s.WaitOne();
                //获取任务
                lock (TaskQueue)
                {
                    try
                    {
                        if (TaskQueue.Count > 0)
                            task = TaskQueue.Dequeue();
                        else
                            task = null;
                    }
                    catch (Exception)
                    {
                        task = null;
                    }
                    if (task == null)
                        continue;
                }
在ThreadPoolManager类中增加两个变量

//因为採用信号量须要定义一个
        public int MaxJobNum = 1000;
        public static Semaphore s;

并在初始化这个类时 初始化信号量 s = new Semaphore(0, MaxJobNum);

这样就行实现同步

以下给出一个測试类

 static void Main(string[] args)
        {
            ThreadPoolManager tpm = new ThreadPoolManager(2);

            TestTask t1 = new TestTask("task1");
            TestTask t2 = new TestTask("task2");
            TestTask t3 = new TestTask("task3");
            TestTask t4 = new TestTask("task4");
            TestTask t5 = new TestTask("task5");
            TestTask t6 = new TestTask("task6");
            TestTask t7 = new TestTask("task7");
            TestTask t8 = new TestTask("task8");
            TestTask t9 = new TestTask("task9");

            tpm.AddTask(t1);
            tpm.AddTask(t2);
            tpm.AddTask(t3);
            tpm.AddTask(t4);
            tpm.AddTask(t5);
            tpm.AddTask(t6);
            tpm.AddTask(t7);
            tpm.AddTask(t8);
            tpm.AddTask(t9);
        }

技术分享


方法二

我们不是用信号量。我们使用AutoResetEvent来实现同步

第一步。在ThreadPoolManager初始化时候创建一个  locks = new AutoResetEvent(false);
当AddTask的时候locks.Set();通知等待的操作。

然后我们对WorkThread的run函数做一个小小的改动
 public void run()
        {
            while (flag && TaskQueue != null)
            {
                //等待任务
                //ThreadPoolManager.sep.WaitOne();

                //等待任务
                while (TaskQueue.Count == 0 && flag)
                {
                    try
                    {
                        ThreadPoolManager.locks.WaitOne();
                    }
                    catch (Exception)
                    {
                    }
                }
                //获取任务
                lock (TaskQueue)
                {
                    try
                    {
                        task = TaskQueue.Dequeue();
                    }
                    catch (Exception)
                    {
                        task = null;
                    }
                    if (task == null)
                        continue;
                }
                try
                {
                    task.SetEnd(false);
                    task.StartTask();
                }
                catch (Exception)
                {
                }
                try
                {
                    if (!task.IsEnd())
                    {
                        task.SetEnd(false);
                        task.EndTask();
                    }
                }
                catch (Exception)
                {
                }

            }//end of while
        }
仅仅有当task列表的数量为0时我们才堵塞,直到AddTask的时候才继续下去

c#自己实现线程池功能(二)