简单看看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 ...
随机推荐
- Java工程图标前面的红色叹号
有时Java工程图标前面会出现一个红色的叹号,这是因为工程引入的jar包不存在(或者被删除.移动)造成的. 右键点击工程,选择Build Path->Configure Build Path,弹 ...
- Yii2框架打包成Phar包报错的经历
以yii2为例 打包文件过程比较简单,但打包好以后简单测试yii命令,一直报错: PHP Fatal error: Uncaught yii\base\InvalidParamException: T ...
- 制作Java视频播放器
一.工程准备 首先需要下载并安装VLC播放器,然后下载vlcj外部库. 下载slf4j中的slf4j-api-1.7.13.jar. slf4j- nop-1.7.13.jar 将vlc安装目录下的l ...
- hibernate3
hibernate3 (整合到spring中的core核心配置中的hibernate3) <!-- 基于hibernate的Session工厂 --> <bean id=" ...
- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
场景:eclipse中编写java中用到数组 问题: 程序不报错但是运行过程中 终止,显示字样 “ Exception in thread "main" java.lang.Arr ...
- java 数据库连接池
1. About java利用jdbc直接连接数据库,经常取得连接,用完释放,很浪费系统资源 2. Code Java代码 package com.cdv.mam.db; import java.sq ...
- Java--CyclicBarrier同步屏障原理,使用
package com; import java.util.Map; import java.util.concurrent.BrokenBarrierException; import java.u ...
- 为mongodb数据库添加安全账户
最近的数据库服务器有些不稳定,遇到了黑客的骚扰,mongodb的安全存在一些漏洞.首要任务是给数据库添加账号.之前大家都习惯于mongodb的不加安全账号和密码来连接数据库,那么问题是添加了安全账户后 ...
- jvm三的三种类加载器
JVM有三种类加载器:bootstrap负责加载系统类,extclassloader负责加载扩展类,appclassloader负责加载应用类.他们主要是分工不一样,各自负责不同的区域,另外也是为了实 ...
- 当struts遇上json,没爱了
用过struts的人,或者用过spring MVC的人,都知道domain model接受参数是多么的方便,而且又有依赖注入,简直是自动拿参数,再自动帮你转成java bean,但是也有不足的地方 说 ...