线程池的技术背景
线程池技术怎样提高server程序的性能
我所提到server程序是指可以接受客户请求并能处理请求的程序。而不仅仅是指那些接受网络客户请求的网络server程序。
多线程技术主要解决处理器单元内多个线程运行的问题,它能够显著降低处理器单元的闲置时间,添加处理器单元的吞吐能力。
但假设对多线程应用不当,会添加对单个任务的处理时间。能够举一个简单的样例:
如果在一台server完毕一项任务的时间为T
T1 创建线程的时间 T2 在线程中运行任务的时间。包含线程间同步所需时间 T3 线程销毁的时间
显然T = T1+T2+T3。注意这是一个极度简化的如果。
能够看出T1,T3是多线程本身的带来的开销。我们渴望降低T1,T3所用的时间。从而降低T的时间。但一些线程的使用者并没有注意到这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。
显然这是突出了线程的弱点(T1,T3),而不是长处(并发性)。
线程池技术正是关注怎样缩短或调整T1,T3时间的技术,从而提高server程序性能的。它把T1,T3分别安排在server程序的启动和结束的时间段或者一些空暇的时间段,这样在server程序处理客户请求时,不会有T1。T3的开销了。
线程池不仅调整T1,T3产生的时间段,并且它还显著降低了创建线程的数目。在看一个样例:
如果一个server一天要处理50000个请求,而且每一个请求须要一个单独的线程完毕。我们比較利用线程池技术和不利于线程池技术的server处理这些请求时所产生的线程总数。在线程池中,线程数通常是固定的。所以产生线程总数不会超过线程池中线程的数目或者上限(下面简称线程池尺寸)。而如果server不利用线程池来处理这些请求则线程总数为50000。一般线程池尺寸是远小于50000。所以利用线程池的server程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。
这些都是如果,不能充分说明问题,以下我将讨论线程池的简单实现并对该程序进行对照測试,以说明线程技术长处及应用领域。
线程池的简单实现及对照測试
一般一个简单线程池至少包括下列组成部分。
- 线程池管理器(ThreadPoolManager):用于创建并管理线程池
- 工作线程(WorkThread): 线程池中线程
- 任务接口(Task):每一个任务必须实现的接口,以供工作线程调度任务的运行。
-
任务队列:用于存放没有处理的任务。
提供一种缓冲机制。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
namespace ThreadManager
{
public class ThreadPoolManager
{
private int MaxThreadNum;
private int MinThreadNum;
private int GrowStepNum;
//线程数量
public int ThreadNum{get;set;}
//默认线程数量
public int DefaultThreadNum { get; set; }
private Queue<Task> TaskQueue;
private Queue<WorkThread> WorkThreadList;
public ThreadPoolManager(int i)
{
TaskQueue = new Queue<Task>();
WorkThreadList = new Queue<WorkThread>();
DefaultThreadNum = 10;
if (i > 0)
DefaultThreadNum = i;
CreateThreadPool(i);
}
public ThreadPoolManager():this(10)
{
}
public bool IsAllTaskFinish()
{
return TaskQueue.Count == 0;
}
public void CreateThreadPool(int i)
{
if (WorkThreadList == null)
WorkThreadList = new Queue<WorkThread>();
lock (WorkThreadList)
{
for (int j = 0; j < i;j++)
{
ThreadNum++;
WorkThread workthread = new WorkThread(ref TaskQueue,ThreadNum);
WorkThreadList.Enqueue(workthread);
}
}
}
public void AddTask(Task task)
{
if (task == null)
return;
lock (TaskQueue)
{
TaskQueue.Enqueue(task);
}
//Monitor.Enter(TaskQueue);
//TaskQueue.Enqueue(task);
//Monitor.Exit(TaskQueue);
}
public void CloseThread()
{
//Object obj = null;
while (WorkThreadList.Count != 0)
{
try
{
WorkThread workthread = WorkThreadList.Dequeue();
workthread.CloseThread();
continue;
}
catch (Exception)
{
}
break;
}
}
}
}
工作线程类using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadManager
{
public class WorkThread
{
public int ThreadNum { get; set; }
private bool flag;
private Queue<Task> TaskQueue;
private Task task;
public WorkThread(ref Queue<Task> queue, int i)
{
this.TaskQueue = queue;
ThreadNum = i;
flag = true;
new Thread(run).Start();
}
public void run()
{
while (flag && TaskQueue != null)
{
//获取任务
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
}
public void CloseThread()
{
flag = false;
try
{
if (task != null)
task.EndTask();
}
catch (Exception)
{
}
}
}
}
task类和实现类using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ThreadManager
{
public interface Task
{
/// <summary>
/// set flag of task.
/// </summary>
void SetEnd(bool flag);
/// <summary>
/// start task.
/// </summary>
void StartTask();
/// <summary>
/// end task.
/// </summary>
void EndTask();
/// <summary>
/// get status of task.
/// </summary>
/// <returns></returns>
bool IsEnd();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ThreadManager
{
public class TestTask:Task
{
private bool is_end;
public void SetEnd(bool flag)
{
is_end = flag;
}
public void StartTask()
{
Run();
}
public void EndTask()
{
is_end = true;
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":"+"结束。");
}
public bool IsEnd()
{
return is_end;
}
public void Run()
{
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId+":"+i);
}
}
}
}