介绍
在上一篇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的时候才继续下去