Overview

   如今的应用程序越来越复杂,我们常常需要使用《异步编程:线程概述及使用》中提到的多线程技术来提高应用程序的响应速度。这时我们频繁的创建和销毁线程来让应用程序快速响应操作,这频繁的创建和销毁无疑会降低应用程序性能,我们可以引入缓存机制解决这个问题,此缓存机制需要解决如:缓存的大小问题、排队执行任务、调度空闲线程、按需创建新线程及销毁多余空闲线程……如今微软已经为我们提供了现成的缓存机制:线程池

【C# 线程】线程池 ThreadPool

1、.NET框架为每一个进程提供了一个线程池,每当您启动线程时,都会花费几百微秒来组织诸如新的私有局部变量堆栈之类的东西。
2、只有全局一个队列和n本地线程任务队列,无法取消任务,无法限制任务执行速度等等
3、当一个等待操作完成时,线程池中的一个辅助线程就会执行对应的回调函数
4、线程池中的线程由系统进行管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。
5、线程池线程都是后台线程。每个线程都使用默认堆栈大小1MB,以默认的优先级运行,并处于多线程单元中,您可以随意更改池线程的优先级— 当释放回池时,它将恢复正常。线程池通过共享和回收线程来减少这些开销,从而允许在非常精细的级别应用多线程,而不会降低性能。
6、如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间之后创建另一个辅助线程。
7、但线程的数目永远不会超过最大值。超过最大值的其他线程可以排队,但它们要等到其他线程完成后才启动。
8、如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。
9、一种是用于处理CPU密集型逻辑的工作线程,即它主要使用CPU来执行其逻辑,如任何计算等,另一种是I / O线程,这些线程用于执行I / O请求或耗时的请求,例如读/写到文件系统, 调用数据库或调用任何第三方 API/请求。
10、线程池不保证全局队列工作项的处理顺序
11、如果工作项完成的时间太长(具体多长没有正式公布)线程池会创建更多的工作者线程,如果工作像完成速度开始变快,工作者线程会被销毁
线程池从其池中的一个线程开始。分配任务时,池管理器会"注入"新线程以处理额外的并发工作负载,最高可达最大限制。在足够长的不活动时间后,如果池管理器怀疑这样做会带来更好的吞吐量,则池管理器可能会"停用"线程。
您可以通过调用 来设置池将创建的线程的上限;默认值为:ThreadPool.SetMaxThreads
12、如果全局队列也为空,工作者线程会进入睡眠状态等待事情的发生,如果睡眠了太长时间,他会自己醒来并销毁至深允许系统回收线程使用的资源
13、最好是将线程池看成一个黑盒,不要拿单个应用程序去衡量它的性能,因为它不是针对某个单独应用程序而设计的。线程池内部会更改它的管理线程的方式,所以大多应用程序的性能会变的越来越好

1、线程池的工作原理

【C# 线程】线程池 ThreadPool

线程池的全局队列(global Queue)

 当调用ThreadPool.QueueUserWorkItem()添加工作项时,该工作项会被添加到线程池的全局队列中。线程池中的空闲线程以FIFO的顺序将工作项从全局队列中取出并执行,但并不能保证按某个指定的顺序完成。

       线程的全局队列是共享资源,所以内部会实现一个锁机制。当一个任务内部会创建很多子任务时,并且这些子任务完成得非常快,就会造成频繁的进入全局队列和移出全局队列,从而降低应用程序的性能。基于此原因,线程池引擎为每个线程引入了局部队列。

线程的局部队列(local Queue)

为我们带来两个性能优势:任务内联化(task inlining)和工作窃取机制。

1)   任务内联化(task inlining)----活用顶层任务工作线程

static void Main(string[] args)
{
    Task headTask= new Task(() =>
    {
        DoSomeWork(null);
    });
    headTask.Start();
    Console.Read();
}
private static void DoSomeWork(object obj)
{
    Console.WriteLine("任务headTask运行在线程“{0}”上",
        Thread.CurrentThread.ManagedThreadId);
 
    var taskTop = new Task(() =>
    {
        Thread.Sleep(500);
        Console.WriteLine("任务taskTop运行在线程“{0}”上",
            Thread.CurrentThread.ManagedThreadId);
    });
    var taskCenter = new Task(() =>
    {
        Thread.Sleep(500);
        Console.WriteLine("任务taskCenter运行在线程“{0}”上",
            Thread.CurrentThread.ManagedThreadId);
    });
    var taskBottom = new Task(() =>
    {
        Thread.Sleep(500);
        Console.WriteLine("任务taskBottom运行在线程“{0}”上",
            Thread.CurrentThread.ManagedThreadId);
    });
    taskTop.Start();
    taskCenter.Start();
    taskBottom.Start();
    Task.WaitAll(new Task[] { taskTop, taskCenter, taskBottom });
}
View Code

相关文章: