【.NET Core】多线程之线程池(ThreadPool)详解(一)

简介: 【.NET Core】多线程之线程池(ThreadPool)详解(一)

一、概述

有些应用程序使用多个线程,创建的线程花费大量时间处于休眠状态,等待事件发生,其他线程可能进入睡眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态。为了简化对这些线程的管理,.NET框架为每一个进程提供了一个线程池,使应用程序能够根据需要来有效地利用对个线程。一个线程监视排到线程池的若干个等待操作的状态。让一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数。线程池中的线程由系统进行管理,程序员不需要费力于线程管理,可以几种精力处理应用程序任务。


线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。


二、线程池的应用范围

线程池特别适合于执行一些需要多个线程的任务。使用线程池能够优化这些任务的执行过程,从而提高吞吐量,它不仅能够使用系统针对此进程优化过程,而且还能够使系统针对计算机上的其他进程优化该执行过程。如果需要启动多个不同的任务,而不想分别设置没个线程的属性,则可以使用线程池。


线程池主要应用于以下几种情况:

  • 不需要前台执行的线程
  • 不需要在使用线程具有特定的优先级
  • 线程的执行时间不易过长,否则会使线程阻塞。由于线程池具有最大线程数限制,因此大量阻塞的线程池的线程可能会阻止任务启动。
  • 不需要将线程放入单线程单元。所有ThreadPool线程均不处于多线程单元中。
  • 不需要具有与线程关联的稳定标识,或使某一线程专用于某一任务。

.NET将线程池线程用于多种用途,包括任务并行库(TPL)操作、异步I/O完成、计时器回调、注册等待操、使用委托的异步方法调用和System.Net套接字连接。


三、线程池特性

线程池线程是后台线程。每个线程均使用默认的堆栈大小,以默认的优先级进行,并且位于多线程单元中。一旦线程池中的线程完成任务,它将返回到等待线程队列中。这时开始既可重用它。通过这种重复使用,应用程序可以避免生产为每个任务创建新线程的开销。

每个线程只有一个线程池。

3.1 线程池线程中的异常

线程池线程中未经处理的异常终止该进程。 以下为此规则的三种例外情况:

  • System.Threading.ThreadAbortException在线程池线程中引发,因为调用了Thread.Abort
  • Sytem.AppDomainUnloadedException在线程池线程中引发,因为正在卸载应用程序域。
  • 公共语言运行时或主机进程将终止该线程

3.2 最大线程池线程数

可以排队到线程池中的操作数仅受可用内存限制。但是,线程池会限制进程中可同时处于活动状态的线程数。如果所有线程池线程都处于忙碌状态,则其他工作项将进行排队,直到要执行它们的线程空闲。进程的线程池的默认大小取决于若干因素。可以通过以下两个方法控制线程池的大小:


  • ThreadPool.GetMaxThreads方法来获取线程池的最大线程数。
  • ThreadPool.SetMaxThreads方法来设置最大线程数。

3.3 最小值线程池线程数

线程池根据需要提供新的工作线程或 I/O 完成线程,直到它达到每个类别的指定最小值。 可以使用ThreadPool.GetMinThreads方法来获取这些最小值。


达到最小值时,线程池可以创建其他线程或等待,直到一些任务完成。 线程池创建和销毁工作线程以优化吞吐量,吞吐量被定义为每个单位时间完成的任务数。 线程过少可能无法实现可用资源的最优利用,而线程过多则可能增加资源争用。


四、线程池使用

  • 使用任务并行库(TPL)。默认情况下,TPL类型使用线程池线程来运行任务。
  • 通过从委托代码调用ThreadPool.QueueUserWorkItem并传递表示执行任务的方法的System.Threading.WaitCallback委托来使用线程池。
  • 使用线程池的另外一种方法ThreadPool.RegisterWaitForSingleObject方法并传递在发出信号或超时的时候调用System.Threading.WaitOrTimerCallback委托所表示的方法System,Threading.WaitHandle,从而对于等待操作相关的工作排队。线程池线程用于调用回调方法。
目录
相关文章
|
1天前
|
存储 Linux C语言
c++进阶篇——初窥多线程(二) 基于C语言实现的多线程编写
本文介绍了C++中使用C语言的pthread库实现多线程编程。`pthread_create`用于创建新线程,`pthread_self`返回当前线程ID。示例展示了如何创建线程并打印线程ID,强调了线程同步的重要性,如使用`sleep`防止主线程提前结束导致子线程未执行完。`pthread_exit`用于线程退出,`pthread_join`用来等待并回收子线程,`pthread_detach`则分离线程。文中还提到了线程取消功能,通过`pthread_cancel`实现。这些基本操作是理解和使用C/C++多线程的关键。
|
1天前
|
开发框架 前端开发 .NET
asp.net core 使用 AccessControlHelper 控制访问权限
asp.net core 使用 AccessControlHelper 控制访问权限
|
3天前
|
安全 Java
【极客档案】Java 线程:解锁生命周期的秘密,成为多线程世界的主宰者!
【6月更文挑战第19天】Java多线程编程中,掌握线程生命周期是关键。创建线程可通过继承`Thread`或实现`Runnable`,调用`start()`使线程进入就绪状态。利用`synchronized`保证线程安全,处理阻塞状态,注意资源管理,如使用线程池优化。通过实践与总结,成为多线程编程的专家。
|
3天前
|
Java 开发者
告别单线程时代!Java 多线程入门:选继承 Thread 还是 Runnable?
【6月更文挑战第19天】在Java中,面对多任务需求时,开发者可以选择继承`Thread`或实现`Runnable`接口来创建线程。`Thread`继承直接但限制了单继承,而`Runnable`接口提供多实现的灵活性和资源共享。多线程能提升CPU利用率,适用于并发处理和提高响应速度,如在网络服务器中并发处理请求,增强程序性能。不论是选择哪种方式,都是迈向高效编程的重要一步。
|
3天前
|
Java 开发者
震惊!Java多线程的惊天秘密:你真的会创建线程吗?
【6月更文挑战第19天】Java多线程创建有两种主要方式:继承Thread类和实现Runnable接口。继承Thread限制了多重继承,适合简单场景;实现Runnable接口更灵活,可与其它继承结合,是更常见选择。了解其差异对于高效、健壮的多线程编程至关重要。
|
5天前
|
Java 程序员
Java多线程编程是指在一个进程中创建并运行多个线程,每个线程执行不同的任务,并行地工作,以达到提高效率的目的
【6月更文挑战第18天】Java多线程提升效率,通过synchronized关键字、Lock接口和原子变量实现同步互斥。synchronized控制共享资源访问,基于对象内置锁。Lock接口提供更灵活的锁管理,需手动解锁。原子变量类(如AtomicInteger)支持无锁的原子操作,减少性能影响。
18 3
|
3天前
|
Java
JAVA多线程深度解析:线程的创建之路,你准备好了吗?
【6月更文挑战第19天】Java多线程编程提升效率,通过继承Thread或实现Runnable接口创建线程。Thread类直接继承启动简单,但限制多继承;Runnable接口实现更灵活,允许类继承其他类。示例代码展示了两种创建线程的方法。面对挑战,掌握多线程,让程序高效运行。
|
3天前
|
Java 调度
【实战指南】Java多线程高手秘籍:线程生命周期管理,掌控程序命运的钥匙!
【6月更文挑战第19天】Java多线程涉及线程生命周期的五个阶段:新建、就绪、运行、阻塞和死亡。理解这些状态转换对性能优化至关重要。线程从新建到调用`start()`变为就绪,等待CPU执行。获得执行权后进入运行状态,执行`run()`。遇到阻塞如等待锁时,进入阻塞状态。完成后或被中断则死亡。管理线程包括合理使用锁、利用线程池、处理异常和优雅关闭线程。通过控制这些,能编写更高效稳定的多线程程序。
|
13天前
|
Cloud Native API C#
C#的现代化:.NET Core引领的技术革命
【6月更文挑战第9天】`.NET Core引领C#现代化,实现跨平台革命,提升性能并支持云原生应用。异步编程模型优化体验,统一API简化开发流程。C#应用场景扩展,开发效率提高,技术创新加速,预示其未来在技术领域将持续发挥关键作用。`
28 10
|
9天前
|
Java API
详细探究Java多线程的线程状态变化
Java多线程的线程状态主要有六种:新建(NEW)、可运行(RUNNABLE)、阻塞(BLOCKED)、等待(WAITING)、超时等待(TIMED_WAITING)和终止(TERMINATED)。线程创建后处于NEW状态,调用start()后进入RUNNABLE状态,表示准备好运行。当线程获得CPU资源,开始执行run()方法时,它处于运行状态。线程可以因等待锁或调用sleep()等方法进入BLOCKED或等待状态。线程完成任务或发生异常后,会进入TERMINATED状态。

热门文章

最新文章