在面向对象编程中,经常会面对创建对象和销毁对象的情况,如果不正确处理的话,在短时间内创建大量对象然后执行简单处理之后又要销毁这些刚刚建立的对象,这是一个非常消耗性能的低效行为,所以很多面向对象语言中在内部使用对象池来处理这种情况,以提高性能,比如在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;
using System.Collections;
using System.Diagnostics;
using System;
using System.ComponentModel;namespace ThreadPoolDemo
{class ThreadPoolDemo1{public ThreadPoolDemo1(){}public void Work(){ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));}/// <summary>/// 统计当前正在运行的系统进程信息/// </summary>/// <param name="state"></param>private void CountProcess(object state){Process[] processes = Process.GetProcesses();foreach (Process p in processes){try{Console.WriteLine("Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);}catch (Win32Exception e){Console.WriteLine("ProcessName:{0}", p.ProcessName);}finally{}}Console.WriteLine("获取进程信息完毕。");}/// <summary>/// 获取当前机器系统变量设置/// </summary>/// <param name="state"></param>public void GetEnvironmentVariables(object state){IDictionary list=System.Environment.GetEnvironmentVariables();foreach (DictionaryEntry item in list){Console.WriteLine("key={0},value={1}", item.Key, item.Value);}Console.WriteLine("获取系统变量信息完毕。");}static void Main(string[] args){ThreadPoolDemo1 tpd1 = new ThreadPoolDemo1();tpd1.Work();Thread.Sleep(5000);Console.WriteLine("OK");Console.ReadLine();}}
}

上面这段代码在本机的运行情况如下:

key=Path,value=C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem;C:/Program Files/Microsoft SQL Server/80/Tools/BINN;C:/Program Files/Microsoft SQL Server/80/Tools/Binn/;C:/Program Files/Microsoft SQL Server/90/DTS/Binn/;C:/Program Files/Microsoft SQL Server/90/Tools/binn/;C:/Program Files/Microsoft SQL Server/90/Tools/Binn/VSShell/Common7/IDE/;C:/Program Files/Microsoft Visual Studio 8/Common7/IDE/PrivateAssemblies/;C:/MySQL Server 5.1/bin;C:/php-5.2.9-Win32

key=TEMP,value=C:/DOCUME~1/ZHOUFO~1/LOCALS~1/Temp

key=SESSIONNAME,value=Console

key=PATHEXT,value=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

key=Rav,value=C:/Documents and Settings/All Users/Application Data/Rising/Rav

key=PROCESSOR_ARCHITECTURE,value=x86

key=SystemDrive,value=C:

key=APPDATA,value=C:/Documents and Settings/zhoufoxcn/Application Data

key=windir,value=C:/WINDOWS

key=USERPROFILE,value=C:/Documents and Settings/zhoufoxcn

key=TMP,value=C:/DOCUME~1/ZHOUFO~1/LOCALS~1/Temp

key=USERDOMAIN,value=ZHOU

key=ProgramFiles,value=C:/Program Files

key=FP_NO_HOST_CHECK,value=NO

key=HOMEPATH,value=/Documents and Settings/zhoufoxcn

key=COMPUTERNAME,value=ZHOU

key=USERNAME,value=zhoufoxcn

key=NUMBER_OF_PROCESSORS,value=2

key=PROCESSOR_IDENTIFIER,value=x86 Family 6 Model 15 Stepping 13, GenuineIntel

key=SystemRoot,value=C:/WINDOWS

key=ComSpec,value=C:/WINDOWS/system32/cmd.exe

key=LOGONSERVER,value=//ZHOU

key=CommonProgramFiles,value=C:/Program Files/Common Files

key=PROMPT,value=$P$G

key=PROCESSOR_LEVEL,value=6

key=PROCESSOR_REVISION,value=0f0d

key=VS80COMNTOOLS,value=C:/Program Files/Microsoft Visual Studio 8/Common7/Tools/

key=lib,value=C:/Program Files/SQLXML 4.0/bin/

key=ALLUSERSPROFILE,value=C:/Documents and Settings/All Users

key=VS90COMNTOOLS,value=c:/Program Files/Microsoft Visual Studio 9.0/Common7/Tools/

key=OS,value=Windows_NT

key=HOMEDRIVE,value=C:

获取系统变量信息完毕。

Id:1864,ProcessName:mysqld,StartTime:2010-1-11 8:23:25

Id:3732,ProcessName:HTime,StartTime:2010-1-11 8:32:16

Id:1328,ProcessName:spoolsv,StartTime:2010-1-11 8:23:23

Id:3908,ProcessName:ctfmon,StartTime:2010-1-11 8:32:19

Id:3640,ProcessName:cmd,StartTime:2010-1-11 15:43:04

Id:1488,ProcessName:notepad,StartTime:2010-1-11 15:30:48

Id:3668,ProcessName:conime,StartTime:2010-1-11 15:27:22

Id:964,ProcessName:svchost,StartTime:2010-1-11 8:23:22

Id:1408,ProcessName:svchost,StartTime:2010-1-11 8:23:23

Id:1140,ProcessName:svchost,StartTime:2010-1-11 8:23:22

Id:1940,ProcessName:sqlbrowser,StartTime:2010-1-11 8:23:25

Id:1672,ProcessName:MsDtsSrvr,StartTime:2010-1-11 8:23:24

Id:3540,ProcessName:explorer,StartTime:2010-1-11 8:32:14

Id:3268,ProcessName:wps,StartTime:2010-1-11 14:08:00

Id:1568,ProcessName:inetinfo,StartTime:2010-1-11 8:23:24

Id:588,ProcessName:csrss,StartTime:2010-1-11 8:23:17

Id:3704,ProcessName:360tray,StartTime:2010-1-11 8:32:16

Id:1028,ProcessName:svchost,StartTime:2010-1-11 8:23:22

Id:2184,ProcessName:mqtgsvc,StartTime:2010-1-11 8:23:28

Id:2628,ProcessName:Reflector,StartTime:2010-1-11 15:04:35

Id:3872,ProcessName:devenv,StartTime:2010-1-11 15:26:51

Id:204,ProcessName:ThreadPoolDemo,StartTime:2010-1-11 15:43:26

Id:664,ProcessName:winlogon,StartTime:2010-1-11 8:23:20

Id:840,ProcessName:dexplore,StartTime:2010-1-11 14:50:21

Id:3900,ProcessName:rundll32,StartTime:2010-1-11 8:32:18

Id:1636,ProcessName:mdm,StartTime:2010-1-11 8:23:24

Id:1012,ProcessName:RavMonD,StartTime:2010-1-11 8:23:22

Id:1100,ProcessName:svchost,StartTime:2010-1-11 8:23:22

Id:476,ProcessName:smss,StartTime:2010-1-11 8:23:14

Id:920,ProcessName:svchost,StartTime:2010-1-11 8:23:21

Id:716,ProcessName:services,StartTime:2010-1-11 8:23:21

Id:3052,ProcessName:ThreadPoolDemo.vshost,StartTime:2010-1-11 15:42:27

Id:1448,ProcessName:msdtc,StartTime:2010-1-11 8:23:23

Id:180,ProcessName:mqsvc,StartTime:2010-1-11 8:23:25

Id:2512,ProcessName:iexplore,StartTime:2010-1-11 14:52:29

Id:1888,ProcessName:nvsvc32,StartTime:2010-1-11 8:23:25

Id:728,ProcessName:lsass,StartTime:2010-1-11 8:23:21

Id:2240,ProcessName:alg,StartTime:2010-1-11 8:23:28

Id:3808,ProcessName:jusched,StartTime:2010-1-11 8:32:17

Id:3128,ProcessName:RsTray,StartTime:2010-1-11 8:32:17

Id:1992,ProcessName:svchost,StartTime:2010-1-11 8:23:25

Id:2944,ProcessName:Foxit Reader,StartTime:2010-1-11 14:08:48

Id:4,ProcessName:System,StartTime:1601-1-1 8:00:00

Id:1604,ProcessName:jqs,StartTime:2010-1-11 8:23:24

ProcessName:Idle

获取进程信息完毕。

OK

在上面的代码中我们使用了线程池,并让它执行了两个任务,一个是列出系统当前所有环境变量的值,一个是列出系统当前运行的进程名和它们的启动时间。

当然,优点和缺点总是同时存在的,使用ThreadPool也有一些缺点,使用线程池有如下缺点:

1、一旦加入到线程池中就没有办法让它停止,除非任务执行完毕自动停止;

2、一个进程共享一个线程池;

3、要执行的任务不能有返回值(当然,线程中要执行的方法也是不能有返回值,如果确实需要返回值必须采用其它技巧来解决);

4、在线程池中所有任务的优先级都是一样的,无法设置任务的优先级;

5、不太适合需要长期执行的任务(比如在Windows服务中执行),也不适合大的任务;

6、不能为线程设置稳定的关联标识,比如为线程池中执行某个特定任务的线程指定名称或者其它属性。

如果我们要面临的情况正好是线程池的缺点,那么我们只好继续使用线程而不是线程池。不过在某些情况下使用线程池确实可以带来很多方便的,比如在WEB服务器中,可以使用线程池来处理来自客户端的请求,可以以比较高的性能运行。

转载于:https://my.oschina.net/dyi/blog/354949

多线程编程(3):线程池ThreadPool相关推荐

  1. java多线程编程之线程池技术全面解读

    在多线程编程时,创建线程是十分消耗资源的,当线程创建过多时,便会引发内存溢出,因此引入了线程池技术. 目录 线程池的优势 线程池的创建&使用 线程池的工作原理 线程池的参数 功能线程池 线程池 ...

  2. threadpool的数量_多线程之旅(11)_如何限制系统线程池ThreadPool的最大最小并发数量_SetMaxThreads/SetMinThreads用法...

    ThreadPool有两个设置线程池并发数量的方法,分别是: ThreadPool.SetMinThreads(int workerThreads, int completionPortThreads ...

  3. 《转载》Python并发编程之线程池/进程池--concurrent.futures模块

    本文转载自 Python并发编程之线程池/进程池--concurrent.futures模块 一.关于concurrent.futures模块 Python标准库为我们提供了threading和mul ...

  4. C#.Net使用线程池(ThreadPool)与专用线程(Thread)

    线程池(ThreadPool)使用起来很简单,但它有一些限制: 1. 线程池中所有线程都是后台线程,如果进程的所有前台线程都结束了,所有的后台线程就会停止.不能把入池的线程改为前台线 程. 2. 不能 ...

  5. C# 线程池ThreadPool

    什么是线程池?为什么要用线程池?怎么用线程池? 1. 什么是线程池? .NET Framework的ThreadPool类提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 I/O.代表其他 ...

  6. linux下c语言线程传参数,【linux】C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0...

    C语言多线程中运行线程池,在线程池中运行线程池,,传递的结构体参数值为空/NULL/0 本贴问题,之前已经提问过一次,当时已经解决了,原贴在这里https://segmentfault.com/q/1 ...

  7. Java并发编程一线程池的五种状态

    推荐:Java并发编程汇总 Java并发编程一线程池的五种状态 原文地址 Java多线程线程池(4)–线程池的五种状态 正文 线程池的5种状态:Running.ShutDown.Stop.Tidyin ...

  8. 线程池(ThreadPool)

    线程池ThreadPool 1.线程池简介 2.线程池参数说明(重点) 2.1 常用参数说明 2.2 拒绝策略(重点) 3.线程池底层工作原理 4.入门案例 1.线程池简介   线程池(英语:thre ...

  9. Java线程池ThreadPool详解

    Java线程池ThreadPool详解 1. 线程池概述 1.1 线程池简介 1.2 线程池特点 1.3 线程池解决问题 2. 线程池原理分析 2.1 线程池总体设计 2.6 线程池流转状态 2.2 ...

  10. 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )

    文章目录 前言 一.ThreadPoolExecutor 构造参数 二.newCachedThreadPool 参数分析 三.newFixedThreadPool 参数分析 四.newSingleTh ...

最新文章

  1. Zabbix监控之常用snmp-OID
  2. centos6.0下ffmpeg的安装编译经历
  3. linux日志汇总,Linux日志分析常用命令汇总(示例代码)
  4. WCF 之 消息契约(MessageContract)
  5. 贪吃蛇系列之一——引入
  6. 2019春季学期第四周作业
  7. python远程监控jvm_python和jstat命令采集jvm数据导入zabbix监控-阿里云开发者社区
  8. IDEA autowired校验关闭方法
  9. 阿里云、腾讯云纷纷宕机后,用户只能坐等损失?
  10. php页面重定向到html,javascript-页面重定向(PHP,HTML)
  11. PostgreSQL数据库的安装与配置
  12. 李宏毅机器学习——迁移学习
  13. IIS6同一IP部署多域名证书(部署指南)
  14. net.sf.jasperreports.engine.util.JRFontNotFoundException: Font 黑体 is not available to the JVM. See
  15. 【JanusGraph入门】(第一天,下载项目)
  16. 即席查询(Ad Hoc)入门(Kylin)
  17. MYSQL中AS(取别名)
  18. 如何卸载有密码保护的Symantec Endpoint Protection v11
  19. 易语言 服务端给客户端发弹窗信息源码
  20. 比例运算电路小结(电路组态 输入电阻)

热门文章

  1. 乐山市计算机学校灵异事件,真人真事:我们学校那些灵异的事情(西南交通大学灵异事件)...
  2. 百度可视化工具Sugar简单介绍以及使用说明
  3. 人工智能在计算机领域的应用论文,人工智能应用领域论文 关于人工智能领域的大学论文...
  4. 手机Root与刷机教程
  5. ShareTechnote系列LTE(10):多小区多RAT之间的交互
  6. 江苏计算机小高考2016,2016江苏小高考成绩揭晓 生物化学4A不易
  7. ActiveX开发详解
  8. 独家揭秘影响SEO排名的17项核心因素
  9. uva 10066 The Twin Towers (最长公共子序列)
  10. OrCAD打开工程报错-ERROR(ORCAP-1653)