线程池基础

1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源。

2,线程池是一个线程集合,供应你的用程序使用。

3,每个CLR有一个自己的线程池,线程池由CLR控制的所有的AppDomain共享。

4,CLR初始化的时候,线程池没有线程的。

5,线程池维护一个操作请求队列。当应用程序想要执行一个一步操作的时候,就调用某个方法。将记录项(empty)追加到线程池队列中,然后线程池代码从队列中提取这个记录项,然后将记录项派遣(dispatch)给一个线程池的线程。当线程池线程完成任务后,不会被销毁。该线程会继续返回到线程池中,进入空闲状态,等待另一个请求。

6,多个应用程序向线程池发出多个请求的时候,只会尝试用一个线程来服务,当超过了线程池线程处理速度的时候,会创建额外的线程。

7,当线程池线程空闲一段时间之后,会自己醒来终止自己释放资源

8,线程池分为工作线程(worker)或者I/O线程,工作线程用于操作异步计算限制操作,I/O线程用于通知代码一个异步I/O限制操作已完成。异步编程模型:(Asychronous Programming Model   APM)

执行简单的计算限制操作

      计算限制操作:指需要长时间的计算的线程

1,要将一个异步,计算限制的操作放到线程池的队列中(向线程池添加一个“工作项”),调用ThreadPool类的几个方法:

static Boolean QueueUserWorkItem(WaitCallback callBack)
      static Boolean QueueUserWorkItem(WaitCallback callBack,Object state)

2,线程池以异步调用一个方法

using System;

using System.Threading;

public static class Program{

public static void Main(){
                Console.WriteLine("Main thread:queing an asynchronous operation");

TreadPool.QueueUserWorkItem(ComputeBoundOp,5);

Console.WriteLine("Main thread:Doing other work here....");

Thread.Sleep(10000);

Console.WriteLine("按任意键继续")
          }

private static void ComputeBoundOp(Object state){

Consol.WriteLine("In ComputeBoundOp:state={0}",state);

Thread.Sleep(1000);//模拟其他工作1秒钟

}

}

执行上下文

多任务系统往往需要同时执行多道作业。作业数往往大于机器的CPU数,然而一颗CPU同时只能执行一项任务,为了让用户感觉这些任务正在同时进行,操作系统的设计者巧妙地利用了时间片轮转的方式,CPU给每个任务都服务一定的时间,然后把当前任务的状态保存下来,在加载下一任务的状态后,继续服务下一任务。任务的状态保存及再加载,这段过程就叫做上下文切换。

    1,每个线程都关联了一个执行上下文的数据结构

2,执行上下文包括:安全设置(压缩栈,Thread的Principal属性和windows身份),宿主设置(System.Treading.HostExcepitonContextManager)以及逻辑调用上下文数据(System.Runtime.Remoting.Messaging.CallContext的LogicalSetData和LogicalGetData)

3,线程执行代码有时候会受到执行上下文设置(安全设置居多)的影响

4,线程执行上下文可流动性。一个线程(初始线程)使用另一个线程(辅助线程)执行任务时,前者上下文应该流向(复制)辅助线程(耗性能).

5,阻止上下文的流动,可提高应用程序性能。

协作式取消

      .net Framework提供了一套协作式取消模式,支持显示取消长时间运行的计算限制操作。

System.Thread.CancellationTokenSource对象:

public class CancellationTokenSource : IDisposable
            {
                   //构造函数
                    public CancellationTokenSource();
                   //获取是否已请求取消此

System.Threading.CancellationTokenSource
                    public bool IsCancellationRequested { get; }
                    //获取与此 System.Threading.CancellationTokenSource 关联的                                                                       System.Threading.CancellationToken
                    public CancellationToken Token;
                    //传达取消请求。
                    public void Cancel();
                    //传达对取消的请求,并指定是否应处理其余回调和可取消操作。
                    public void Cancel(bool throwOnFirstException);
             }

这个对象包含了管理取消有关的所有状态。构造好一个CancellationTokenSource(引               用类型)之后,可以从它的Token属性获得一个或多个CancellationToken(值类型)实                 例,并传给你的操作,使那些操作可以取消。以下是CancellationToken值类型最有用               的一些成员:

public struct CancellationToken //一个值类型

            {
               //获取此标记是否能处于已取消状态,IsCancellationRequested 由非通过Task来调用(invoke)的一个操作调用(call)
               public bool IsCancellationRequested { get; }
                 //如果已请求取消此标记,则引发 System.OperationCanceledException,由通    过Task来调用的操作调用
                public void ThrowIfCancellationRequested();
               //获取在取消标记时处于有信号状态的 System.Threading.WaitHandle,取消时,                WaitHandle会收到信号
                public WaitHandle WaitHandle { get; }
              //返回空 CancellationToken 值。
                public static CancellationToken None
             //注册一个将在取消此 System.Threading.CancellationToken 时调用的委托。省略了简单重载版本
                public CancellationTokenRegistration Register(Action<object> callback,                object state, bool useSynchronizationContext);

//省略了GetHashCode、Equals成员
          }

CancellationToken实例是一个轻量级的值类型,它包含单个私有字段:对它的CancellationTokenSource对象的一个引用。在一个计算限制操作的循环中,可以定时调用CancellationToken的IsCancellationRequested属性,了解循环是否应该提前终止,进而终止计算限制的操作。当然,提前终止的好处在于,CPU不再需要把时间浪费在你对其结果已经不感兴趣的一个操作上。

任务

     ThreadPool的QueueUserWorkItem 存在限制,没有一个内建机制让你知道什么时候完成,也没有一个机制在操作完成返回一个值。

     创建任务:

System.Threading.Tasks创建一个任务

创建Task任务调用的构造器,传递一个Action或者Action<Object>委托

取消任务:

用一个CancellationTokenSource取消一个Task。

一个任务完成时自动启动另一个新任务:

调用ContinuWith()使得一个Task完成时调用新的任务-------- wait方法会导致线程堵塞导致消耗性能

创建子任务:

Task<Int32[]> parent=new Task<Int32[]>(()=>{
             var results=new Int32[3];

new Task(()=>results[0])=Sum(10000),TaskCreationOptions.AttacjedToParent).Start();

new Task(()=>results[0])=Sum(20000),TaskCreationOptions.AttacjedToParent).Start();

new Task(()=>results[0])=Sum(30000),TaskCreationOptions.AttacjedToParent).Start();

return results;
       });

//父任务及其子任务运行完成后,用一个延续任务显示结果

var cwt=parent.ContinueWith(parentTask=>Array.Foreach(parentTask.Result,console.Writelin));

任务内部揭秘:

1,每个Task对象包含一组构成任务状态的字段:Int32的ID,Task执行状态的Int32,对父任务的一个引用,对Task创建指定TaskScheduler的一个引用,对回掉方法的一个引用,对传值给回调方法的对象一个引用,对一个ExecutionContext的引用,对ManualResetEventSlim对象的引用,以及一些补充状态的一个引用(CancellationToken,ContinueWithTask队形集合,异常Task集合)

2,Task和Task<TResult>实现了IDisposeable接口,完成后调用Dispose

任务工厂:

TaskFactory 和 TaskFactory<TResult>类

任务调度器:

1,TaskScheduler对象负责任务调度,包含两个派生类:线程池任务调度器(thread pool task scheduler)和同步上下文任务调动起(sysnchronization context task scheduler)

默认是前者调度器。后者应用于windows窗体,wpf和silverlight应用程序。

Pareallel的静态For,ForEach 和Invoke方法:

可以帮助提高性能。

 计算限制操作的定时器:

System.Treading命名空间定义一个Timer类,可以让线程池线程定时调用搞一个方法。

1,线程池为所有的Timer对象只是用了一个线程。这个线程知道下一个Timer对象什么时候触发

2,当下一个Timer对象到期,线程就会唤醒,内部调用ThreadPool的QueueUserWorkItem(工作项),将工作项添加到线程池的队列中。然后等待回调。

3,如果回调方法执行很长,计时器可能会再次触发 .Timeout.Infinite可让计时器只触发一次。

线程池如何管理线程:

1,System.Threading.ThreadPool类提供:GetMaxTreads,SetMaxThreads,GetMinThreads,SetMinThreads和GetAvailableThreads用于查询和设置线程池的线程数。但是,限制线程池的显成熟,会造成应用程序性能变得更差。

2,ThreadPool.QueueUserWorkItem方法和Timer类将工作项放入全局队列中。工作者进程采用的先入先出(FIFO)

算法将工作项取出,并处理他们。所有工作者线程都竞争一个线程同步所。

3,TaskScheduler调度Task对象:非工作者调用Task对象----Task添加到全局队列----Task添加到调用线程的本地队列------工作线程准好处理工作项----检查本地队列查找一个Task------如果本地队列存在一个Task,就从本地队列移除Task,对工作项进行处理(工作者线程采用后入先出(LIFO)取出本地Task)

缓存线和伪共享

1,CPU在芯片上集成了高速缓存(Cache)使得CPU访问RAM速度非常快。

2,CPU在逻辑上讲所有内存划分为“缓冲行”用于进一步提高性能。一个缓冲行由64个字节构成。

最新文章

  1. 在RichFaces中使用Facelets模板
  2. IIS7配置Gzip压缩 JS压强失败的原因
  3. .NET调用window串口读取电子秤的数据
  4. jq 换图片路径
  5. 通过实验分析system_call中断处理过程
  6. 论反馈信息如何推动 IT 运维团队进步?
  7. Java读取一个文件并打印到控制台上
  8. Girls&#39; research - HDU 3294 (Manacher处理回文串)
  9. Layer中自定义属性的动画
  10. uva-11234 Expressions
  11. AVAudioPlayer与MPMusicPlayerController的区别
  12. Dockerfile的指令
  13. jdk1.7 tomcat-7安装
  14. Spring Day 2
  15. Spring Boot 项目实战(四)集成 Redis
  16. IDEA去除自动检测bean是否存在
  17. Delphi 判断时间是否合法 -IsValidDateTime、IsValidDate、IsValidTime、IsValidDateDay
  18. 配置jenkins slave 问题,ERROR: Couldn&#39;t find any revision to build. Verify the repository and branch configuration for this job.
  19. scala 学习笔记九 定义操作符
  20. ubuntu16 jdk7 install&config

热门文章

  1. BZOJ1251——序列终结者
  2. ios7 ios8导航栏透明
  3. 两款基于Jquery的图表插件
  4. 15 BasicHashTable基本哈希表类(二)——Live555源码阅读(一)基本组件类
  5. 给dos命令“.bat”文件换图标
  6. Apache Thrift 环境配置
  7. Maven打包附加配置文件
  8. 实现Redis的主从复制配置
  9. (转)HTTP长连接和短连接
  10. 深入浅出Java回调机制