为何使用线程池? 程序员
在面向对象编程中,建立和销毁对象是很费时间的,由于建立一个对象要获取内存资源或者其它更多资源,因此提升服务程序效率的一个手段就是尽量减小建立和销毁对象的次数,特别是一些很耗资源的对象建立和销毁。如何利用已有对象来服务就是一个须要解决的关键问题,其实这就是一些"池化资源"技术产生的缘由。好比你们所熟悉的数据库链接池正是遵循这一思想而产生的,本文将介绍的线程池技术一样符合这一思想。算法
多线程是什么?组成?特色?数据库
线程池是一种多线程处理形式,处理过程当中将任务添加到队列,而后在建立线程后自动启动这些任务。线程池中的线程由系统管理,程序员不须要费力于线程管理,能够集中精力处理应用程序任务。编程
特色:安全
何时使用线程池? 服务器
一、GetMaxThreads() : 获取能够同时处于活动状态的线程池请求的最大数目。全部大于此数目的请求将保持排队状态,直到线程池线程变为可用。多线程
参数1:workerThreads :线程池中辅助线程的最大数目。
参数2:completionPortThreads :线程池中异步 I/O 线程的最大数目。 异步
二、GetMinThreads() 获取线程池维护的最小空闲线程数。 函数
三、SetMaxThreads() 设置能够同时处于活动状态的线程池的最大请求数目(不考虑计算机处理器的数目)性能
参数1:workerThreads::要由线程池维护的新的最小空闲辅助线程数。
参数2:completionPortThreads::要由线程池维护的新的最小空闲异步 I/O 线程数。
返回值:若是更改为功,则为 true;不然为 false。
四、SetMinThreads() 设置线程池在新请求预测中维护的空闲线程数(不考虑计算机处理器的数目)
参数1:workerThreads:要由线程池维护的新的最小空闲辅助线程数。
参数2:completionPortThreads:要由线程池维护的新的最小空闲异步 I/O 线程数。
返回值:若是更改为功,则为 true;不然为 false。
五、GetAvailableThreads() 获取由 GetMaxThreads 返回的线程池线程的最大数目和当前活动数目之间的差值。
参数1:workerThreads:可用辅助线程的数目。
参数2:completionPortThreads:可用异步 I/O 线程的数目。
六、QueueUserWorkItem() 将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。
返回值:若是将方法成功排入队列,则为 true;不然为 false。
参数2:state :包含方法所用数据的对象。
返回值:若是将方法成功排入队列,则为 true;不然为 false。
备注:WaitCallback 回调方法必须与System.Threading.WaitCallback委托类型相匹配。
WaitCallback函数原型:public delegate void WaitCallback(Object state);调用QueueUserWorkItem能够经过Object来向任务过程传递参数。若是任务过程须要多个参数,能够定义包含这些数据的类,并将类的实例强制转换为Object数据类型。
七、UnsafeQueueUserWorkItem() 非安全性注册一个等待 WaitHandle 的委托(将方法排入队列以便执行)。
八、RegisterWaitForSingleObject() 将指定的委托排队到线程池。当发生如下状况之一时,辅助线程将执行委托。
九、UnsafeRegisterWaitForSingleObject() 非安全性将指定的委托排队到线程池。
线程池示例?
咱们先来看一个简单的线程实例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Begin in Main"); Thread t = new Thread(ThreadInvoke); t.IsBackground = true; t.Start(); //将当前线程挂起200毫秒 Thread.Sleep(200); Console.WriteLine("End in Main"); Console.ReadKey(); } static void ThreadInvoke(object obj) { for (int i = 0; i < 5; i++) { Console.WriteLine("Execute in ThreadInvoke"); //每隔100毫秒,循环一次 Thread.Sleep(100); } } } }
"End in Main"并无在ThreadInvoke()方法中全部代码执行完以后才输出。
因而可知Main方法和ThreadInvoke是并行执行的
使用线程池改造上边的示例:
上面介绍了只是一个最简单的有关线程线程的例子,但在实际开发中使用的线程每每是大量的和更为复杂的,这时,每次都建立线程、启动线程。从性能上来说,这样作并不理想(由于每使用一个线程就要建立一个,须要占用系统开销);从操做上来说,每次都要启动,比较麻烦。为此引入的线程池的概念。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Begin in Main"); ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadInvoke)); Console.WriteLine("End in Main"); //将当前线程挂起200毫秒 Thread.Sleep(3000); Console.ReadKey(); } static void ThreadInvoke(object obj) { for (int i = 0; i < 5; i++) { Console.WriteLine("Execute in ThreadInvoke"); //每隔100毫秒,循环一次 Thread.Sleep(100); } } } }
Thread.Sleep(3000)这句话是必须的由于当Main方法结束后,.Net环境会自动结束销毁线程池,为了保证完成线程池里的任务,因此主线程须要等待一段时间。
由输出结果可知,Main方法和ThreadInvoke方法是并行执行的。