线程池ThreadPool
在面向对象编程中,经常会面对创建对象和销毁对象的情况,如果不正确处理的话,在短时间内创建大量对象然后执行简单处理之后又要销毁这些刚刚建立的对象,这是一个非常消耗性能的低效行为,所以很多面向对象语言中在内部使用对象池来处理这种情况,以提高性能,比如在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();
- }
- }
- }
在上面的代码中我们使用了线程池,并让它执行了两个任务,一个是列出系统当前所有环境变量的值,一个是列出系统当前运行的进程名和它们的启动时间。
当然,优点和缺点总是同时存在的,使用ThreadPool也有一些缺点,使用线程池有如下缺点:
1、一旦加入到线程池中就没有办法让它停止,除非任务执行完毕自动停止;
2、一个进程共享一个线程池;
3、要执行的任务不能有返回值(当然,线程中要执行的方法也是不能有返回值,如果确实需要返回值必须采用其它技巧来解决);
4、在线程池中所有任务的优先级都是一样的,无法设置任务的优先级;
5、不太适合需要长期执行的任务(比如在Windows服务中执行),也不适合大的任务;
6、不能为线程设置稳定的关联标识,比如为线程池中执行某个特定任务的线程指定名称或者其它属性。
如果我们要面临的情况正好是线程池的缺点,那么我们只好继续使用线程而不是线程池。不过在某些情况下使用线程池确实可以带来很多方便的,比如在WEB服务器中,可以使用线程池来处理来自客户端的请求,可以以比较高的性能运行。
线程池ThreadPool的更多相关文章
- 线程池ThreadPool的初探
一.线程池的适用范围 在日常使用多线程开发的时候,一般都构造一个Thread示例,然后调用Start使之执行.如果一个线程它大部分时间花费在等待某个事件响应的发生然后才予以响应:或者如果在一定期间内重 ...
- C#多线程学习 之 线程池[ThreadPool](转)
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 高效线程池(threadpool)的实现
高效线程池(threadpool)的实现 Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线 ...
- 多线程系列 线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- C# -- 使用线程池 ThreadPool 执行多线程任务
C# -- 使用线程池 ThreadPool 执行多线程任务 1. 使用线程池 class Program { static void Main(string[] args) { WaitCallba ...
- 多线程Thread,线程池ThreadPool
首先我们先增加一个公用方法DoSomethingLong(string name),这个方法下面的举例中都有可能用到 #region Private Method /// <summary> ...
- C# 线程池ThreadPool的用法简析
https://blog.csdn.net/smooth_tailor/article/details/52460566 什么是线程池?为什么要用线程池?怎么用线程池? 1. 什么是线程池? .NET ...
- 多线程系列(2)线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 线程池ThreadPool的常用方法介绍
线程池ThreadPool的常用方法介绍 如果您理解了线程池目的及优点后,让我们温故下线程池的常用的几个方法: 1. public static Boolean QueueUserWorkItem(W ...
随机推荐
- 《Structuring Machine Learning Projects》课堂笔记
Lesson 3 Structuring Machine Learning Projects 这篇文章其实是 Coursera 上吴恩达老师的深度学习专业课程的第三门课程的课程笔记. 参考了其他人的笔 ...
- Django使用消息提示简单的弹出个对话框
1.下面就来介绍一下如何简单的显示一个消息提示,好像js可以控制,不过这里用了django.contrib.messages这个库 2.首先呢,在项目的settings.py有默认配置一个django ...
- ROC曲线详解
转自https://blog.csdn.net/qq_26591517/article/details/80092679 1 ROC曲线的概念 受试者工作特征曲线 (receiver operatin ...
- 在web项目中获取ApplicationContext上下文的3种主要方式及适用情况
最近在做web项目,需要写一些工具方法,涉及到通过Java代码来获取spring中配置的bean,并对该bean进行操作的情形.而最关键的一步就是获取ApplicationContext,过程中纠结和 ...
- 【HANA系列】SAP HANA SQL字符串连接操作
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL字符串连 ...
- spring @valid 注解
用于验证注解是否符合要求,直接加在变量之前,在变量中添加验证信息的要求,当不符合要求时就会在方法中返回message 的错误提示信息. @PostMapping public User create ...
- 【AMAD】Stream-Framework -- 让你可以使用Cassandra和Redis构建新闻feed,活动流(activity stream)以及通知系统。
动机 简介 个人评分 动机 你曾经是否想为你自己的网站构建Facebook,Github那种feed流. 简介 通过Stream-Framework1你可以做到: Github那种活动流 Twitte ...
- NOIp2013D2T3 华容道【搜索&图论-最短路】
题目传送门 暴力搜索 看到这道题的第一反应就是直接上$bfs$啦,也没有想到什么更加优秀的算法. 然后就是$15$分钟打了$70$分,有点震惊,纯暴力诶,这么多白给分嘛,太划算了,这可是$D2T3$诶 ...
- NIO 编程模型
NIO 编程模型 Doug Lea 在 Scalable IO in Java 的 PPT 中描述了 Reactor 编程模型的思想,大部分 NIO 框架和一些中间件的 NIO 编程都与它一样或是它的 ...
- python smtplib server not connect
最近发现用smtplib发邮件一直发送不成功,使用debug发现前面都正常,但是DATA发送直接被smtp服务器直接断开.smtp服务器显示body丢失. 后来发现是我加了附件,有指定文件类型: at ...