代码改变世界

多线程学习系列:(五)线程池基础上

2011-01-27 11:31  微软一点都不软  阅读(189)  评论(0编辑  收藏  举报

池(Pool)是一个很常见的提高性能的方式。比如线程池连接池等,之所以有这些池是因为线程和数据库连接的创建和关闭是一种比较昂贵的行为。对于这种昂贵的资源我们往往会考虑在一个池容器中放置一些资源,在用的时候去拿,在不够的时候添点,在用完就归还,这样就可以避免不断的创建资源和销毁资源。

  如果您做过相关实验的话可能会觉得不以为然,似乎开1000个线程也用不了几百毫秒。我们要这么想,对于一个高并发的环境来说,每一秒假设有100个请求,每个请求需要使用(开和关)10个线程,也就是一秒需要处理1000个线程的开和关,每个线程独立堆栈1M,可以想象在这一秒中内存分配和回收是多么夸张,这个开销不能说不昂贵。

  首先,要理解线程池线程分为两类工作线程和IO线程,可以单独设置最小线程数和最大线程数:

ThreadPool.SetMinThreads(2, 2); 
ThreadPool.SetMaxThreads(4, 4);

  最大线程数很好理解,就是线程池最多创建这些线程,如果最大4个线程,现在这4个线程都在运行的话,后续进来的线程只能排队等待了。那么为什么有最小线程一说法呢?其实之所以使用线程池是不希望线程在创建后运行结束后理解回收,这样的话以后要用的时候还需要创建,我们可以让线程池至少保留几个线程,即使没有线程在工作也保留。上述语句我们设置线程池一开始就保持2个工作线程和2个IO线程,最大不超过4个线程。

  至于线程池的使用相当简单先来看一段代码:

for (int i = 0; i < totalThreads; i++) 
{ 
  ThreadPool.QueueUserWorkItem(o => 
  { 
    Thread.Sleep(1000); 
    int a, b; 
    ThreadPool.GetAvailableThreads(out a, out b); 
    Console.WriteLine(string.Format("({0}/{1}) #{2} : {3}", a, b, Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("mm:ss"))); 
  }); 
} 
Console.WriteLine("Main thread finished"); 
Console.ReadLine();