C#如何实现自定义线程池(云服务器、云主机、高防IP、高防服务器、香港服务器、美国服务器,开发技术)

时间:2024-04-30 13:12:45 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

在项目中如果是web请求时候,IIS会自动分配一个线程来进行处理,如果很多个应用程序共享公用一个IIS的时候,线程分配可能会出现一个问题(当然也是我的需求造成的)

之前在做项目的时候,有一个需求,就是当程序启动的时候,希望能够启动一定数目的线程,然后每一个线程始终都是在运行的状态,不进行释放,然后循环去做一些事情。那么IIS的线程管理可能就不是我想要的,因为我想我的一些程序,只用我开启的线程来做工作。也就是说我想模拟一个线程池,每次有一个调用的时候从自定义线程池中取出一个,用完再放回去。

谈谈我的思路:

1.程序一启动就通过for循环来创建,一定数目的线程(这个数目是可以配置的)

2.至少要有三个容器来存储线程,分别是工作线程队列和空闲线程队列以及等待队列

3.使用线程中的AutoResetEvent类,初始每一个线程都是unsignaled状态,线程一启动就一直在循环调用WaitOne()方法,那么每次外部调用的时候,都调用一次这个类实例对象的set,线程然后就可以继续做下面的工作了。

4.至少两个方法:

第一个开放给外部,让外部的方法能够被传入执行,然后这个方法能够判断空闲队列,等待队列,以及工作队列的状态,如果传入的时候发现,空闲队列有空闲的线程就直接,将任务委托给空闲队列的一个线程执行,否则把它放到等待队列。

第二个方法,需要能够将工作完成的线程从工作队列移动到空闲队列,然后判断一下等待队列是不是有任务,有的话就交给空闲队列里面的线程来执行。

体思路如上,可以试试先写一下。

1.因为每个线程都有一个AutoResetEvent的实例,所以最好把Thread进行封装,变成我们自己的Thread。

publicclassTask{#regionVariable//一个AutoResetEvent实例privateAutoResetEvent_locks=newAutoResetEvent(false);//一个Thread实例privateThread_thread;//绑定回调方法,就是外部实际执行的任务publicAction_taskAction;//定义一个事件用来绑定工作完成后的操作,也就是4中所说的工作队列向空闲队列移动publiceventAction<Task>WorkComplete;///<summary>///设置线程拥有的Key///</summary>publicstringKey{get;set;}#endregion//线程需要做的工作privatevoidWork(){while(true){//判断信号状态,如果有set那么_locks.WaitOne()后的程序就继续执行_locks.WaitOne();_taskAction();//执行事件WorkComplete(this);}}#regionevent//构造函数publicTask(){//スレッドオブジェクトを初期化する_thread=newThread(Work);_thread.IsBackground=true;Key=Guid.NewGuid().ToString();//线程开始执行_thread.Start();}//Set开起信号publicvoidActive(){_locks.Set();}#endregion}

解释:上面那个Key的作用,因为多个线程同时进行的时候,我们并不知道哪一个线程的工作先执行完,所以说上面的工作队列,实际上应该用一个字典来保存,这样我们就能在一个线程结束工作之后,通过这 里的KEY(每个线程不一样),来进行定位了。

2.线程封装好了,然后就可以实现线程池了

publicclassTaskPool{#regionVariable//创建的线程数privateint_threadCount;//空闲线程队列privateQueue<Task>_freeQueue;//工作线程字典(为什么?)privateDictionary<string,Task>_workingDictionary;//空闲队列,存放需要被执行的外部函数privateQueue<Action>_waitQueue;#endregion#regionEvent//自定义线程池的构造函数publicTaskPool(){_workingDictionary=newDictionary<string,Task>();_freeQueue=newQueue<Task>();_waitQueue=newQueue<Action>();_threadCount=10;Tasktask=null;//产生固定数目的线程for(inti=0;i<_threadCount;i++){task=newTask();//给每一个任务绑定事件task.WorkComplete+=newAction<Task>(WorkComplete);//将每一个新创建的线程放入空闲队列中_freeQueue.Enqueue(task);}}//线程任务完成之后的工作voidWorkComplete(Taskobj){lock(this){//将线程从字典中排除_workingDictionary.Remove(obj.Key);//将该线程放入空闲队列_freeQueue.Enqueue(obj);//判断是否等待队列中有任务未完成if(_waitQueue.Count>0){//取出一个任务Actionitem=_waitQueue.Dequeue();TasknewTask=null;//空闲队列中取出一个线程newTask=_freeQueue.Dequeue();//线程执行任务newTask._taskAction=item;//把线程放入到工作队列当中_workingDictionary.Add(newTask.Key,newTask);//设置信号量newTask.Active();return;}else{return;}}}//添加任务到线程池publicvoidAddTaskItem(ActiontaskItem){lock(this){Tasktask=null;//判断空闲队列是否存在线程if(_freeQueue.Count>0){//存在线程,取出一个线程task=_freeQueue.Dequeue();//将该线程放入工作队列_workingDictionary.Add(task.Key,task);//执行传入的任务task._taskAction=taskItem;//设置信号量task.Active();return;}else{//空闲队列中没有空闲线程,就把任务放到等待队列中_waitQueue.Enqueue(taskItem);return;}}}#endregion}

解释:这里的两个方法,基本符合我的设想,注意每一个方法里面都有lock操作,这就保证了,多个线程进行操作相同的队列对象的时候,能够进行互斥。保证一个时间只有一个线程在操作。

测试代码:

classProgram{staticvoidMain(string[]args){TaskPool_taskPool=newTaskPool();Console.WriteLine(Thread.CurrentThread.ManagedThreadId);for(vari=0;i<20;i++){_taskPool.AddTaskItem(Print);}Console.Read();}publicstaticvoidPrint(){Console.WriteLine("DoSomething!");}}

这里我执行了20次print操作,看看结果是啥:

C#如何实现自定义线程池

从图中看到20次确实执行了,但是看不到线程是哪些,稍微修改一下自定义的线程池。

1.在自定义线程的构造函数中添加:如下代码,查看哪些线程被创建了

publicTask(){_thread=newThread(Work);_thread.IsBackground=true;Key=Guid.NewGuid().ToString();//线程开始执行_thread.Start();Console.WriteLine("Thread:"+_thread.ManagedThreadId+"hasbeencreated!");}

2.在线程完成工作方法之后添加如下代码,查看哪些线程参与执行任务

privatevoidWork(){while(true){//判断信号状态,如果有set那么_locks.WaitOne()后的程序就继续执行_locks.WaitOne();_taskAction();Console.WriteLine("Thread:"+Thread.CurrentThread.ManagedThreadId+"workComplete");//执行事件WorkComplete(this);}}

3.修改客户端程序

classProgram{staticvoidMain(string[]args){TaskPool_taskPool=newTaskPool();for(vari=0;i<20;i++){_taskPool.AddTaskItem(Print);}Console.Read();}publicstaticvoidPrint(){Thread.Sleep(10000);}}

测试结果:

C#如何实现自定义线程池

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:C#如何实现自定义线程池的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Java编译错误信息提示java.lang.ExceptionInInitializer如何解决下一篇:

21 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18