在面向对象编程中,经常会面对创建对象和销毁对象的情况,如果不正确处理的话,在短时间内创建大量对象然后执行简单处理之后又要销毁这些刚刚建立的对象,这是一个非常消耗性能的低效行为,所以很多面向对象语言中在内部使用对象池来处理这种情况,以提高性能,比如在ADO.NET内部就允许使用数据库连接池来提高性能,在JDBC中没有提供数据库连接池,一些开发人员为了提高效率就自己编写数据库连接池来提高性能,当然据我所知在Java中有些框架提供了数据库连接的池化处理。
在多线程编程时也会遇到上面的情况,如果创建了过多的线程将会增加操作系统资源的占用,并且还要处理资源要求和潜在的占用冲突,并且使用了多线程之后将使代码的执行流程和资源竞争情况变得复杂,稍不留心就会产生bug(在第二篇中在我写的代码中就曾经出现过一个bug,后来我自己发现并处理了这个bug)。在使用多线程编程时对需要同步的资源访问尤其需要注意,如系统资源(系统端口等)、共享资源(文件、窗口句柄等)、属于单个应用程序的资源(如全局、静态和实例字段或属性)。
针对上面的情况,我们可以使用线程池来解决上面的大部分问题,跟使用单个线程相比,使用线程池有如下优点:
1、缩短应用程序的响应时间。因为在线程池中有线程的线程处于等待分配任务状态(只要没有超过线程池的最大上限),无需创建线程。
2、不必管理和维护生存周期短暂的线程,不用在创建时为其分配资源,在其执行完任务之后释放资源。
3、线程池会根据当前系统特点对池内的线程进行优化处理。
总之使用线程池的作用就是减少创建和销毁线程的系统开销。在.NET中有一个线程的类ThreadPool,它提供了线程池的管理。
ThreadPool是一个静态类,它没有构造函数,对外提供的函数也全部是静态的。其中有一个QueueUserWorkItem方法,它有两种重载形式,如下:
public static bool QueueUserWorkItem(WaitCallback callBack):将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。
public static bool QueueUserWorkItem(WaitCallback callBack,Object state):将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。
QueueUserWorkItem方法中使用的的WaitCallback参数表示一个delegate,它的声明如下:
public delegate void WaitCallback(Object state)
如果需要传递任务信息可以利用WaitCallback中的state参数,类似于ParameterizedThreadStart委托。
下面是一个ThreadPool的例子,代码如下:
using System.Threading;
02 using System.Collections;
03 using System.Diagnostics;
04 using System;
05 using System.ComponentModel;
06
07 // 作者:周公的专栏
08 // http://blog.csdn.net/zhoufoxcn/archive/2010/01/11/5177579.aspx
09 namespace ThreadPoolDemo
10 {
11 class ThreadPoolDemo1
12 {
13 public ThreadPoolDemo1()
14 {
15 }
16
17 public void Work()
18 {
19 ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
20 ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
21 }
22 /// <summary>
23 /// 统计当前正在运行的系统进程信息
24 /// </summary>
25 /// <param name="state"></param>
26 private void CountProcess(object state)
27 {
28 Process[] processes = Process.GetProcesses();
29 foreach (Process p in processes)
30 {
31 try
32 {
33 Console.WriteLine("Id:{0},ProcessName:{1},StartTime:{2}",
34 p.Id, p.ProcessName, p.StartTime);
35 }
36 catch (Win32Exception e)
37 {
38 Console.WriteLine("ProcessName:{0}", p.ProcessName);
39 }
40 finally
41 {
42 }
43 }
44 Console.WriteLine("获取进程信息完毕。");
45 }
46 /// <summary>
47 /// 获取当前机器系统变量设置
48 /// </summary>
49 /// <param name="state"></param>
50 public void GetEnvironmentVariables(object state)
51 {
52 IDictionary list=System.Environment.GetEnvironmentVariables();
53 foreach (DictionaryEntry item in list)
54 {
55 Console.WriteLine("key={0},value={1}", item.Key, item.Value);
56 }
57 Console.WriteLine("获取系统变量信息完毕。");
58 }
59
60 static void Main(string[] args)
61 {
62 ThreadPoolDemo1 tpd1 = new ThreadPoolDemo1();
63 tpd1.Work();
64 Thread.Sleep(5000);
65
66 Console.WriteLine("OK");
67
68 Console.ReadLine();
69 }
70 }
71 }