1、.NET框架为每一个进程提供了一个线程池,每当您启动线程时,都会花费几百微秒来组织诸如新的私有局部变量堆栈之类的东西。
2、只有全局一个队列和n本地线程任务队列,无法取消任务,无法限制任务执行速度等等
3、当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数
4、线程池中的线程由系统进行管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
5、线程池线程都是后台线程。每个线程都使用默认堆栈大小1MB,以默认的优先级运行,并处于多线程单元中,您可以随意更改池线程的优先级— 当释放回池时,它将恢复正常。线程池通过共享和回收线程来减少这些开销,从而允许在非常精细的级别应用多线程,而不会降低性能。
6、如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。
7、但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。
8、果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。
1、.net 会为每个进程生成一个线程池。线程池的初始值线程数是 cpu内核数。后面连续建线程要每间隔500ms新建一个线程。即使突然并发大量任务也是按这个进度进来线程。
2、可以通过设置min thread(默认等于cpu内核数) 提高 线程池一开始的线程数,从而提高并发数。 后面连续建线程要每间隔500ms新建一个线程。
3、本地队列:线程池中的每一个线程都会绑定一个 ThreadPoolWorkQueueThreadLocals 实例,在 workStealingQueue 这个字段上保存着本地队列。
4、全局队列:每个进程只有一个全局队列, 是由 ThreadPoolWorkQueue 维护的,同时它也是整个队列系统的入口,直接被 ThreadPool 所引用。
5、在线程池线程A中生成的任务,会安排入当前线程A的任务队列。
6、当前线程池的线程A的任务队列已经执行完成,如果全局任务队列也没有任务了,就会去查看其他线程B的任务队列,如果其他线程B的任务队列还有很对没完成的,当前线程A就会偷它B的任务执行。
参考:https://www.cnblogs.com/eventhorizon/p/15316955.html#ithreadpoolworkitem-%E5%AE%9E%E7%8E%B0%E7%B1%BB%E7%9A%84%E5%AE%9E%E4%BE%8B
在以下几种情况下,适合于使用线程池线程:
(1)不需要前台执行的线程。
(2)不需要在使用线程具有特定的优先级。
(3)线程的执行时间不易过长,否则会使线程阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池线程可能会阻止任务启动。
(4)不需要将线程放入单线程单元。所有 ThreadPool 线程均不处于多线程单元中。
(5)不需要具有与线程关联的稳定标识,或使某一线程专用于某一任务。
(6)一种是在应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应,这一般使用ThreadPool(线程池)来解决
(7)一种情况是在线程平时都处于休眠状态,只是周期性地被唤醒,这一般使用Timer(定时器)来解决。下面对ThreadPool类进行详细说明。
ThreadPool.QueueUserWorkItem
BackgroundWorker
System.Timers.Timer
和System.Threading.Timer
WebClient
Begin
线程池从其池中的一个线程开始。分配任务时,池管理器会"注入"新线程以处理额外的并发工作负载,最高可达最大限制。在足够长的不活动时间后,如果池管理器怀疑这样做会带来更好的吞吐量,则池管理器可能会"停用"线程。
您可以通过调用 来设置池将创建的线程的上限;默认值为:ThreadPool.SetMaxThreads
max threads 初始值:32位平台 1023,64位平台 short.MaxValue。
min threads 初始值:运行环境 CPU 核心数,可通过 ThreadPool.SetMinThreads
进行设置,参数有效范围是 [1, max threads]。(这些数字可能因硬件和操作系统而异。之所以存在许多线程,是为了确保某些线程被阻止时取得进展(在等待某些条件时空转,例如来自远程计算机的响应)。
您还可以通过调用 来设置下限。下限的作用更微妙:它是一种高级优化技术,指示池管理器在达到下限之前不要延迟线程的分配。当存在阻塞的线程时,提高最小线程计数可提高并发性(请参阅侧边栏)。ThreadPool.SetMinThreads