通常用到线程池时,会用到“生产者-消费者”模型。
如果项目中不好实现“生产者”这一角色,而是预先开好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;
}
}
}
}