一個用來“拉”任務的簡單執行緒池 c#版
阿新 • • 發佈:2019-01-24
通常用到執行緒池時,會用到“生產者-消費者”模型。
如果專案中不好實現“生產者”這一角色,而是預先開好N條執行緒,然後讓執行緒自己去“拉”任務,“拉”到有任務就處理,然後再“拉”任務,這樣實現起來很簡單,但任務的源頭若是一直沒有任務,這N條執行緒依然是不停地在“拉”,消耗著CPU資源。於是想出了以下方案:
開好N條執行緒
1.第一條執行緒在迴圈“拉”任務,其他的在阻塞(這樣就不佔CPU資源了)。
2.直到第一條執行緒拉到有任務,先“告訴”其他執行緒:我有活幹了,你們誰有空的去“源頭”把風,有活你們接著幹。
3.其中一條執行緒站了出來(簡稱第二條),同樣是迴圈“拉”任務,如果此時“源頭”還有任務,第二條執行緒同樣先“告訴”其他還在阻塞的執行緒,自己然後幹活。
4.第三條站了現來,不停在迴圈“拉”任務。
5.第一和第二條幹完活了,變成了阻塞狀態,等通知(此時在把風的執行緒)。
照著這樣的思路,用C#寫了以下模型,不知.NET庫裡是否有現成的,若有,就當學習吧
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace testMutex
{
class Program
{
int threadPollMaxNUM = 3; //最大執行緒數
Thread thread3;
Mutex mutex;
object lockObject = new object();
public Program()
{
mutex = new Mutex();
}
static void Main(string[] args)
{
Program p = new Program();
p.RunThread();
}
public void RunThread()
{
for (int i = 0 ; i < threadPollMaxNUM; i++)
{
thread3 = new Thread(new ThreadStart(testFunc_three));
thread3.Name = "thread" + i;
thread3.Start();
}
string re = Console.ReadLine();
if (re == "exit")
{
running = false;
}
}
private void TestFunc(string str)
{
Console.WriteLine("{0} {1}", str, System.DateTime.Now.Millisecond.ToString());
Thread.Sleep(50);
}
private void TestFunc_one(string str)
{
Console.WriteLine("sinco{0}{1}", str, System.DateTime.Now.Millisecond.ToString());
Thread.Sleep(5000);
}
//以下是彈性處理任務的模型
bool running = true;
private void testFunc_three()
{
while (running)
{
mutex.WaitOne();
//bool _havaTask = false;
//lock (lockObject)
//{
int ix = 0; //僅作為自動退出用,實際用時不需要
bool _havaTask = false;
while (_havaTask == false && running)
{
Console.WriteLine("{0} checking...", Thread.CurrentThread.Name);
_havaTask = getOneTask();
if (_havaTask == false)
{
//real sleep
Thread.Sleep(4000);
ix++;
if (ix > 5) { running = false; }//僅作為自動退出用,實際用時不需要
}
}
//}
//'' ""
mutex.ReleaseMutex();
if (_havaTask)
{
Console.WriteLine("{0} working...", Thread.CurrentThread.Name);
//do some thing....
Thread.Sleep(5000);
Console.WriteLine("{0} end !", Thread.CurrentThread.Name);
}
}
Console.WriteLine("{0} exit !", Thread.CurrentThread.Name);
}
int u = 0;
/// <summary>
/// 假設這是一個拉任務的方法
/// </summary>
/// <returns></returns>
private bool getOneTask()
{
if (u < 6)
{
u++;
Thread.Sleep(1000);
return true;
}
else
{
//Thread.Sleep(30 * 1000);
//running = false;
return false;
}
}
}
}