C#线程池

  1. using System.Threading;
  2.      
  3. namespace Threadsss
  4. {
  5.     class Program
  6.     {
  7.          static void ThreadMethod(object state)
  8.          {
  9.              Console.WriteLine("线程开始:"+ Thread.CurrentThread.ManagedThreadId);
  10.              Thread.Sleep(2000);
  11.              Console.WriteLine("线程结束");
  12.          }  

  13.          static void Main(string[] args)
  14.          {
  15.             ThreadPool.QueueUserWorkItem(ThreadMethod);  
  16.             ThreadPool.QueueUserWorkItem(ThreadMethod); 
  17.             ThreadPool.QueueUserWorkItem(ThreadMethod); 
  18.             ThreadPool.QueueUserWorkItem(ThreadMethod); 
  19.          
  20.             Console.ReadKey();
  21.           }
  22.   
  23.       
  24.   
  25.       }
  26.    
  27.    }  



**************************    相关      ****************************************

线程池的技术背景

在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源, 所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。比如大家所熟悉的数据库连接池正是遵循这一思想而产生的,本文将介绍的线程池技术同样符合这一思想。

线程池技术如何提高服务器程序的性能

我所提到服务器程序是指能够接受客户请求并能处理请求的程序,而不只是指那些接受网络客户请求的网络服务器程序。

多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。但如果对多线程应用不当,会增加对单个任务的处理时间。可以举一个简单的例子:

假设在一台服务器完成一项任务的时间为T

     T1 创建线程的时间
      T2 在线程中执行任务的时间,包括线程间同步所需时间
      T3 线程销毁的时间

显然T = T1+T2+T3。注意这是一个极度简化的假设。

可以看出T1,T3是多线程本身的带来的开销,我们渴望减少T1,T3所用的时间,从而减少T的时间。但一些线程的使用者并没有注意到这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。显然这是突出了线程的弱点(T1,T3),而不是优点(并发性)。

线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。

线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目。在看一个例子:

假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。我们比较利用线程池技术和不利于线程池技术的服务器处理这些请求时所产生的线程总数。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目或者上限(以下简称线程池尺寸),而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池尺寸是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。

有关线程池的解释请参考:

http://www.cnblogs.com/JeffreyZhao/archive/2009/07/22/thread-pool-1-the-goal-and-the-clr-thread-pool.html


把上面的代码修改之后如下:

class Program
{  static void Main(string[] args)
    {  Console.WriteLine("Begin in Main");
        //Thread thread = new Thread(new ThreadStart(ThreadInvoke));
        启动线程
        //thread.Start(); 
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadInvoke)); 
        //将当前线程挂起200毫秒
        Thread.Sleep(200);
        Console.WriteLine("End in Main"); 
        Thread.Sleep(3000);
    } 
    static void ThreadInvoke(Object param)
    {   for (int i = 0; i < 5; i++)
        {   Console.WriteLine("Execute in ThreadInvoke");
            //每隔100毫秒,循环一次
            Thread.Sleep(100);
        }
    }
}

 

输出结果:

C# <wbr>线程池ThreadPool的用法

上面的代码把线程的创建和启动改为了ThreadPool.QueueUserWorkItem(newWaitCallback(ThreadInvoke)),方法ThreadInvoke加了个参数(Object param),并在Main结束之间加了Thread.Sleep(3000)Thread.Sleep(3000)这句话是必须的因为当Main方法结束后,.Net环境会自动结束销毁线程池,为了保证完成线程池里的任务,所以主线程需要等待一段时间。 

由输出结果可知,Main方法和ThreadInvoke方法是并行执行的。 


另附一篇简单实现线程池的实例:
程序中定义了一个对象类,用以包装参数,实现多个参数的传递。成员属性包括两个输入参数和一个输出参数。

  1. using System;
  2. using System.Threading;
  3.  
  4. class Packet    //定义对象类,用来包装参数,实现多个参数的传递
  5. {
  6.     Protected internal String inval1;
  7.     Protected interval String inval2;
  8.     Protected interval String outval;
  9. class ThreadPoolExam     //定义执行相同内容的两个方法
  10. {
  11.    public void Task1(object Obj)   
  12.    {   
  13.         Packet PacketObj;         //声明Packet类对象,用来传递参数
  14.         PackerObj = (Packet)Obj ; 
  15.         Console.WriteLine("任务1中的第一个参数:"+ PacketObj.inval1);
  16.         Console.WriteLine("任务1中的第二个参数:"+ PacketObj.inval2);
  17.           
  18.         PacketObj.outval = PacketObj.inval1 + " " +PacketObj.inval2;
  19.     }  
  20.     
  21.     public void Task2(object Obj)   
  22.     {
  23.         Packet PacketObj;
  24.         PackerObj = (Packet)Obj ;
  25.         Console.WriteLine("任务1中的第一个参数:"+ PacketObj.inval1);
  26.         Console.WriteLine("任务1中的第二个参数:"+ PacketObj.inval2);
  27.         
  28.         PacketObj.outval = PacketObj.inval1 + " " +PacketObj.inval2;
  29.     }
  30.   
  31.      static void Main()
  32.      {
  33.          Packet PacketObj1 = new Packet();  //声明两个Packet对象,并为输入参数赋值
  34.          Packet PacketObj2 = new Packet();
  35.       
  36.          PacketObj1.inval1 = "这是任务1的参数1";
  37.          PacketObj1.inval2 = "这是任务1的参数2";
  38.          PacketObj2.inval1 = "这是任务2的参数1";
  39.          PacketObj2.inval2 = "这是任务2的参数2";
  40.   
  41.          ThreadPoolExam tps = new ThreadPoolExam();        //以下放入线程池

  42.          ThreadPool.QueueUserWorkItem(new WaitCallback(tps.Task1), PacketObj1);  
  43.          ThreadPool.QueueUserWorkItem(new WaitCallback(tps.Task2), PacketObj2);
  44.    
  45.        Console.ReadKey();
  46.   }
  47. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屠变恶龙之人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值