博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程系列(三):线程池基础
阅读量:5295 次
发布时间:2019-06-14

本文共 3906 字,大约阅读时间需要 13 分钟。

目录:

  • 为什么要使用线程池
  • 简单的线程池操作
  • 执行上下文
  • 协作式取消

一、为什么要使用线程池:线程池概念理解

备注:线程池中的线程是后台线程。

1、为什么会有线程池?

  因为创建线程和销毁线程相对来说需要消耗大量的时间和资源。 太多的线程会浪费内存。

       操作系统需要在线程间来回切换,线程过多,有损性能。

2、线程池是什么?

  线程池就是一个可持续性发展的线程集合,线程池内部维护着一个消息队列。

  当一条方法名引用追加到线程池的队列中,线程池会提取当前项,派发给线程池中空闲的线程。

3、线程池创建线程策略?

  • 如果线程池中没有线程,就创建一个线程。
  • 如果并发的请求数过多,且请求速度超出线程池处理速度,就会创建额外线程。
  • 如果线程完成任务,不会销毁,会进入空闲状态,等待下个请求的响应。
  • 如果在一定的时间内没有接收到请求,超度空闲,就会自己醒来,终止自己,释放资源。

 

二、简单的线程池操作

我们上面提到过,线程池内维护的了一个消息队列,方法引用追加到队列中,线程池中的线程从队列中取出等待执行。

[SecuritySafeCritical] public static bool QueueUserWorkItem(WaitCallback callBack);
[SecuritySafeCritical] public static bool QueueUserWorkItem(WaitCallback callBack, object state);

委托:

[ComVisible(true)]  public delegate void WaitCallback(object state);

所以,一个是参数为null,一个是需要传递实参的委托。要使用以上方式向队列中添加工作项,其实是将方法引用添加到队列中

1、我们定义一个符合 WaitCallback 规则的委托 一个参数且没有返回值

public static void WorkerFun(object flag)   {            Console.WriteLine("【WorkerFun】 doing ........");            for (int index = 10; index > 0; index--)            {                Console.WriteLine("     {0}s", index);                Thread.Sleep(2000);            }      Console.WriteLine("【WorkerFun】end.");    }

2、我们使用线程池进行异步调用

public void Run(string args){    Console.WriteLine("【Main】doing......");    if (ThreadPool.QueueUserWorkItem(WorkerFun))    {        Console.WriteLine("Add pool success");    }    Console.WriteLine("【Main】sleep 5s.");    Thread.Sleep(5000);     Console.WriteLine("【Main】end."); }

运行结果:

主线程执行完毕,子线程自动关闭。所以说,线程池中的线程都是后台线程,优先级比较低。

 

二、执行上下文

1、为什么要有执行上下文 ?

线程在执行代码时,会受到上下文的影响。

上下文会从初始线程流向辅助线程,这样这整个线程使用相同的安全设置和宿主设置。

同样,辅助线程可以使用初始线程的逻辑上下文。

namespace System.Threading
//执行上下文  public sealed class ExecutionContext : IDisposable, ISerializable    {        //从当前线程捕获执行上下文         [SecuritySafeCritical]        public static ExecutionContext Capture();          //是否取消了执行上下文的流动                public static bool IsFlowSuppressed();         //恢复执行上下文在异步线程之间的流动                public static void RestoreFlow();               //在当前线程上的指定执行上下文中运行某个方法        [SecurityCritical]        public static void Run(ExecutionContext executionContext, ContextCallback callback, object state);                //取消执行上下文在异步线程之间的流动          [SecurityCritical]        public static AsyncFlowControl SuppressFlow();         //创建当前执行上下文的副本                   [SecuritySafeCritical]        public ExecutionContext CreateCopy();         [SecuritySafeCritical]        public void Dispose();               [SecurityCritical]        public void GetObjectData(SerializationInfo info, StreamingContext context);    }

通过执行上下文我们来控制上下文的流动。

CallContext.LogicalSetData("Name", "sc");//默认允许上下文进行流动ThreadPool.QueueUserWorkItem(state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));//现在禁止流动ExecutionContext.SuppressFlow();ThreadPool.QueueUserWorkItem(state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));//恢复流动ExecutionContext.RestoreFlow();Console.ReadKey();

运行:第一行允许流动;第二行禁止流动

Name=scName=

 

三、协作式取消和超时

需要取消的模式必须显示支持取消

//通知 System.Threading.CancellationToken,告知其应被取消public sealed class CancellationTokenSource : IDisposable

CancellationTokenSource  管理 着取消相关的状态.

所谓协作式,首先我自己要支持取消,接收信号后任务终止。

private static void Count(System.Threading.CancellationToken token, int countto){    for (int count = 0; count < countto; count++)    {        Console.WriteLine("index:{0}", count);        if (token.IsCancellationRequested)        {            Console.WriteLine("Count is cancelled  {0}",count);            break;        }    }}

 主线程中,接收协作式取消命令,子线程检测到信号后,主动停止。

public void Run(string args){             System.Threading.CancellationTokenSource cts = new CancellationTokenSource();    //开启线程    ThreadPool.QueueUserWorkItem(state => Count(cts.Token, 10000000));    Console.WriteLine("Press 
to cancel the operation"); Console.ReadLine(); cts.Cancel(); Console.ReadLine();}

 运行结果:主线程发出回车信号,子线程检测到信号后结束任务。

 

转载于:https://www.cnblogs.com/sunchong/p/8654899.html

你可能感兴趣的文章
C# 测算代码运行时间 Stopwatch
查看>>
用js互相调用iframe页面内的js函数
查看>>
SSH原理和使用
查看>>
初级PHPer的进阶之路
查看>>
c++ bind
查看>>
Linux上安装JDK1.7步骤
查看>>
微信聊天和通讯录按钮样式
查看>>
一步一步学EF系列【4、升级篇 实体与数据库的映射】live writer真坑,第4次补发...
查看>>
决策树
查看>>
对称加密和非对称加密
查看>>
python时间序列数据的对齐和数据库的分批查询
查看>>
OpenJudge 2712
查看>>
ubuntu+github配置使用
查看>>
练习015:删除排序数组中的重复项
查看>>
UML用例图总结
查看>>
POJ 2117 求无向图的割点
查看>>
2016.12.13
查看>>
一.安全NA之syslog SNMP SSH NTP
查看>>
HTTP状态码
查看>>
python的re模块
查看>>