昨天寫的 基於信號量Semaphore的c#線程池設計 在實際使用中,容易造成CPU占用偏高,筆者分析認為是由於信號量本身的缺點造成的,因此筆者重新設計了一款更高效的c#線程池,完全不使用waithandle之類的阻塞線程,而是使用更為簡單的最大線程數值(一個long整數)來控制線程的運行。如果超過指定的線程數,那麼保存在hash表中的線程進入等待隊列,當有空閒位置時,才會釋放出一個等待隊列中的線程啟動並運行。
筆者粗略地計算了下,此種方法比基於信號量的效率要高30左右,性能提高是顯著的^_^,下面為大家展示代碼。
public class MyThreadManager : MyThreadPool, iThreadManager
{ //線程池的啟動、停止控制大同小異,不再贅述
private bool bStart;
private bool bPause;
private bool bStoped;
public bool Running
{
get { return bStart && !bPause && !bStoped; }
}
public MyThreadManager(int num):base(num)
{
ControlCallback = new ThreadControl(Run);
bStart = false;
bPause = false;
bStoped = false;
}
public virtual void Start()
{
bStart = true;
bPause = false;
bStoped = false;
}
public void Stop()
{
bPause = true;
bStart = false;
bStoped = false;
}
public void Pause()
{
bStoped = true;
bStoped = false;
bPause = false;
}
public void Resume()
{
bPause = false;
bStoped = false;
bStart = true;
}
public void Run()
{
while(!bStart || bPause || bStoped){
if (bStoped)
{
Thread.CurrentThread.Abort();
}
Thread.Sleep(20);
}
while (Interlocked.Read(ref iRunningThreadNum) > Interlocked.Read(ref iMaxThreadNum))
{
Thread.Sleep(20);
}
Interlocked.Increment(ref iRunningThreadNum); //增加線程池中運行的線程數量
}
}
public class MyThreadPool
{
protected Hashtable m_Pool;
protected Queue<string> m_Queue;
protected ThreadControl m_control;
public ThreadControl ControlCallback
{
set
{
m_control = value;
}
get
{
return m_control;
}
}
protected long iMaxThreadNum;
public long MaxThreadNum
{
get
{
return Interlocked.Read(ref iMaxThreadNum);
}
}
private long iQueueSize;
protected long iRunningThreadNum;
public long RunningThreadNum
{
get { return Interlocked.Read(ref iRunningThreadNum); }
}
public MyThreadPool(int num)
{
iMaxThreadNum = num;
iRunningThreadNum = 0;
iQueueSize = 0;
m_Pool = new Hashtable(num);
m_Queue = new Queue<string>();
}
public void QueueWorkItem(ThreadCallback callback, object obj)
{
Thread thread = new Thread(delegate()
{
if (m_control != null)
m_control();
callback(obj); //這裡是實際執行的函數
m_Pool.Remove(Thread.CurrentThread.Name); //將當前線程移出線程池
Interlocked.Decrement(ref iRunningThreadNum); //運行線程數遞減
ReleaseQueue(); //釋放等待隊列中的線程
});
string threadGuid = Guid.NewGuid().ToString();
thread.Name = threadGuid; //保證線程命名唯一
m_Pool.Add(threadGuid,thread);
if (Interlocked.Read(ref iRunningThreadNum) < Interlocked.Read(ref iMaxThreadNum))
{
thread.Start();
}
else
{
m_Queue.Enqueue(thread.Name);
Interlocked.Increment(ref iQueueSize);
}
}
private void ReleaseQueue() //如果等待隊列中有線程存在則釋放一個,並做減計數
{
if (Interlocked.Read(ref iQueueSize) > 0)
{
string threadname = "";
lock (m_Queue)
{
threadname = m_Queue.Dequeue();
Interlocked.Decrement(ref iQueueSize);
}
Thread t = m_Pool[threadname] as Thread;
t.Start();
}
}
}
public interface iThreadManager
{
void Start();
void Stop();
void Pause();
void Resume();
void Run();
}
}