简单看看ThreadPool的源码以及从中看出线程间传值的另一种方法
这几天太忙没时间写博客,今天回家就简单的看了下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的源码以及从中看出线程间传值的另一种方法的更多相关文章
- zeromq源码分析笔记之线程间收发命令(2)
在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...
- 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理
前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...
- Java并发包源码学习系列:线程池ScheduledThreadPoolExecutor源码解析
目录 ScheduledThreadPoolExecutor概述 类图结构 ScheduledExecutorService ScheduledFutureTask FutureTask schedu ...
- v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码
百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...
- JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析
JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- 从源码角度来分析线程池-ThreadPoolExecutor实现原理
作为一名Java开发工程师,想必性能问题是不可避免的.通常,在遇到性能瓶颈时第一时间肯定会想到利用缓存来解决问题,然而缓存虽好用,但也并非万能,某些场景依然无法覆盖.比如:需要实时.多次调用第三方AP ...
- Java并发包源码学习系列:线程池ThreadPoolExecutor源码解析
目录 ThreadPoolExecutor概述 线程池解决的优点 线程池处理流程 创建线程池 重要常量及字段 线程池的五种状态及转换 ThreadPoolExecutor构造参数及参数意义 Work类 ...
- Netty源码分析之Reactor线程模型详解
上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...
随机推荐
- 炉石传说 C# 开发笔记(BS上线尝试)
昨天买了一个月的1G 1核的服务器,由于不是新用户,所以没有享受到阿里的6个月免费的优惠. (阿里脑残,为什么不对于续费或者升级免费呢?) 在服务器的通讯上面已经OK了,完全绕过了ASP.NET,就是 ...
- avalon.js 1.4.6简单列表数据绑定ms-repeat ms-click
1.列表数据绑定 <html> <head> <meta charset="UTF-8"> <meta name="viewpo ...
- 重写onStart()函数
Android开发中有时会遇到这种情况,在数据列表的Activity中点击添加按钮,弹出另一个Activity添加数据,这样返回数据列表的Activity时就需要刷新数据列表(因为添加了一条数据).这 ...
- FreeBSD pkg仓库有台湾的镜像了
http://pkg.freebsd.org/ 在这个页面上可以看到: pkg0.bme.freebsd.org pkg0.nyi.freebsd.org pkg0.twn.freebsd.org p ...
- AngularJS的ng-click传参
<ul id="dataSet" ng-repeat="item in infos" ng-model="dataSet"> & ...
- Java--如何使用sun.misc.Unsafe完成compareAndSwapObject原子操作
package com; import sun.misc.Unsafe; import java.lang.reflect.Field; /** * Created by yangyu on 16/1 ...
- Jquery实际应用,判断radio,selelct,checkbox是否选中及选中的值
jquery取radio单选按钮的值 $("input[name='items']:checked").val(); 另:判断radio是否选中并取得选中的值 如下所示: fun ...
- Git修改提交的用户名和Email
git config --global user.name "Your Name" git config --global user.email you@example.com
- 一个完整的类用来生成RSACryptoServiceProvider单例类(.NET)
internal class CcbRsaCryptProvider { private static RSACryptoServiceProvider _providerForSign; priva ...
- jQuery Transit 过渡效果
jQuery Transit 使用 CSS3 的新特性来实现过渡效果,比默认的.animate方法要顺畅得多. 因为使用 CSS3 进行过渡效果,所以对不支持 CSS3 的浏览器效果有所下降. 语法和 ...