这几天太忙没时间写博客,今天回家就简单的看了下ThreadPool的源码,发现有一个好玩的东西,叫做”执行上下文“,拽名叫做:”ExecutionContext“。

一:ThreadPool的大概流程。

第一步:它会调用底层一个helper方法。

第二步:走进这个helper方法,我们会发现有一个队列,并且这个队列的item必须是QueueUserWorkItemCallback的实例,然后这就激发了我的

兴趣,看看QueueUserWorkItemCallback到底都有些什么?

第三步:走到QueueUserWorkItemCallback实例的时候,会依次把callback,state参数给当前类的字段,并且有一个好玩的地方的就是根据

     ExecutionContext.IsFlowSuppressed()来判断要不要把”当前线程的上下文“给”调用线程“?这个放在后面讲,然后我们看到了一

    个 IThreadPoolWorkItem.ExecuteWorkItem()方法,里面有ContextCallback委托的调用,也许这个就是队列中每一项中要调用

    的方法。

第四步:然后我们再回到第二步中的 ThreadPoolGlobals.workQueue.Enqueue(callback, true)方法进去看看,并且我们的callback,state都被封装成了

      QueueUserWorkItemCallback放到队列中了,从这个Enqueue方法中,我们看到了一个this.EnsureThreadRequested(),走到方法里面去了

    之后,这时候急迫想去看ThreadPool.RequestWorkerThread()方法,但它是个extern方法,不过从名字上看就是请求工作线程去执行,所以并

    没有真实的发现到所谓的线程池这个东西。(由于不能窥全貌,可能有些说的不太对)

好了,上面的剖析大概就这样了,其实所有的方法都封装成了底层的一个类放在一个队列中,应该是用上面的for来挑选空闲的工作线程去执行我们

的任务,里面还有很多代码,比较复杂,一时也看不懂什么。

二:执行上下文

  刚才第三步说到了”执行上下文“,看到这个方法里面有一个if条件,然后看到有一个 ExecutionContext.IsFlowSuppressed()方法,从名字上

就可以看出叫”阻止流动“,如果为否的话,就用Capture来抓当前线程的”上下文信息“,然后我们就顺藤摸瓜的往下看,从这个方法来看,我们依次

去抓取调用线程的”安全设置“,”宿主设置“,”同步信息“,“逻辑调用”,并且可以看到logicalCallContext有值的话,会做一个copy的操作。

其实这个logicalCallContext非常有意思,里面是一个KV结构,源码里面也说了,只要我不IsFlowSuppressed,那么主线程的上下文会flow到

工作线程,那么logicalCallContext怎么设置呢?其实在C#里面的CallContext里面的LogicalSetData和LogicalGetData就可以做这些事情。

     class Program
{
static void Main(string[] args)
{
CallContext.LogicalSetData("name", "ctrip"); Thread.CurrentThread.IsBackground = true; ThreadPool.QueueUserWorkItem((o) =>
{
var t = Thread.CurrentThread.ManagedThreadId; var result = CallContext.LogicalGetData("name"); Console.WriteLine("我是工作线程: Name:" + result); }); Console.Read();
}
}

可以看到我在主线程设置的值被工作线程读到了,是不是很有意思,给我们线程间传值提供了另一种方法,刚才我们也看到,一旦IsFlowSuppressed

了,那么context就返回null,也就阻止了将logicCallContext的信息传递给工作线程,可以用ExecutionContext.SuppressFlow()做到,下面具体

看一看。

   class Program
{
static void Main(string[] args)
{
CallContext.LogicalSetData("name", "ctrip"); //阻止logical数据流动
ExecutionContext.SuppressFlow(); Thread.CurrentThread.IsBackground = true; ThreadPool.QueueUserWorkItem((o) =>
{
var t = Thread.CurrentThread.ManagedThreadId; var result = CallContext.LogicalGetData("name"); Console.WriteLine("我是工作线程: Name:" + result); }); Console.Read();
}
}

现在结论也出来了,去Capture主线程的上下文是需要很多的代码量,所以如果工作线程用不到主线程的这些信息,那么你应该做到显示关闭,这样

对工作线程的性能来说有很大的好处。

简单看看ThreadPool的源码以及从中看出线程间传值的另一种方法的更多相关文章

  1. zeromq源码分析笔记之线程间收发命令(2)

    在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...

  2. 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

    前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...

  3. Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析

    目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...

  4. v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码

    百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...

  5. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

  6. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...

  7. 从源码角度来分析线程池-ThreadPoolExecutor实现原理

    作为一名Java开发工程师,想必性能问题是不可避免的.通常,在遇到性能瓶颈时第一时间肯定会想到利用缓存来解决问题,然而缓存虽好用,但也并非万能,某些场景依然无法覆盖.比如:需要实时.多次调用第三方AP ...

  8. Java并发包源码学习系列:线程池ThreadPoolExecutor源码解析

    目录 ThreadPoolExecutor概述 线程池解决的优点 线程池处理流程 创建线程池 重要常量及字段 线程池的五种状态及转换 ThreadPoolExecutor构造参数及参数意义 Work类 ...

  9. Netty源码分析之Reactor线程模型详解

    上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...

随机推荐

  1. ubuntu16.4下用jexus部署asp.net core rtm

    上篇文章介绍了下用vs发布部署到iis环境,今天说下ubuntu 下部署asp.net core,不需要安装.net core sdk,自带运行时方式部署,利用jexus服务器转发请求到asp.net ...

  2. Tomcat8访问管理页面localhost出现:403 Access Denied

    问题: Access Denied You are not authorized to view this page. If you have already configured the Manag ...

  3. ArrayList和LinkedList的区别

    简单的说,ArrayList是顺序存储,而LinkedList是链式存储.

  4. 高德携手阿里云发布“LBS云”,账户打通只是第一步

    位置.游戏.视频,是公认的基于云计算的三大移动端应用方向.而今,LBS云有了更多进展,在高价值应用与云平台之间实现了资源打通和融合,高德迈出了实质性的一步. 高德地图副总裁郄建军(左)与阿里云业务总经 ...

  5. RecyclerView和PullToRefreshListView的对比

    项目中上拉刷新和下拉加载一直都是比较常见的:以前一般都是重写ListView或直接用PullToRefreshListView的框架:最近尝试用RecyclerView来实现下拉加载上拉刷新也是不错的 ...

  6. 项目总结笔记系列 Maven Session1

    主题:Maven 参考地址: 1.http://www.yiibai.com/maven/ 2.http://www.icoolxue.com/ 目录 1.环境搭建 2.pom.xml文件解析 3.m ...

  7. python2.x 默认编码问题

    python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自己总结一篇文章. 我也会在以后学习中,不断的修改此篇博客. 这里假设读者已有与编码相关的 ...

  8. 初学C++之自定义类型名简化

    说明:本人使用的是vc++ IDE:vs2013 我在自定义一些类时,有时会取一些很长的名字,但是这不利于使用,这个时候就可以使用类型名简化. class MathAddBBBB { }; using ...

  9. Release编译模式下,事件是否会引起内存泄漏问题初步研究

    题记:不常发生的事件内存泄漏现象 想必有些朋友也常常使用事件,但是很少解除事件挂钩,程序也没有听说过内存泄漏之类的问题.幸运的是,在某些情况下,的确不会出问题,很多年前做的项目就跑得好好的,包括我也是 ...

  10. Scroll Depth – 衡量页面滚动的 Google 分析插件

    Scroll Depth 是一个小型的 Google Analytics(谷歌分析)插件,可以让你衡量用户在页面上滚动了多远.它可以监控 25%.50%.75% 和 100% 四个滚动点,并发送谷歌分 ...