Netty学习之旅----ThreadLocal原理分析与性能优化思考(思考篇)

  • @return the current thread’s value of this thread-local

*/

public T get() {

Thread t = Thread.currentThread(); //@1

ThreadLocalMap map = getMap(t); //@2

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this); //@3

if (e != null)

return (T)e.value;

}

return setInitialValue(); // @4

}

代码@1:获取当前线程。

代码@2:从当前线程获取ThreadLocalMap。

ThreadLocalMap getMap(Thread t) {

return t.threadLocals;

}

这里是直接返回线程对象的threadLocals变量,有点意思吧,所以说ThreadLocal,是线程的本地变量,就是这层意思,真正存放数据的地方,就是线程对象本身,其实接下来的会更加有意思:我们进入ThreadLocalMap源码分析,得知,原来ThreadLocalMap就是一个Map结构(K-V)键值对,关于里面的源码就不一一分析了,ThreadLocalMap(ThreadLocal firstKey, Object firstValue),firstKey 为ThreadLocal,神奇吧,其实这也是为什么Thread的本地变量的数据类型为Map的原型,一个线程可以被多个ThreadLocal关联,每声明一个,就在线程的threadLocals增加为一个键值对,key 为 ThreadLocal,而value为具体存放的对象。

代码@3:如果线程的ThreadLocalMap不为空,则直接返回对,否则进入到代码@4

代码@4:初始化并获取放入ThreadLocal中的变量。

上面就是ThreadLocal的核心设计理念,为了更加直观的说明ThreadLocal原理,举例说明:


public class ThreadLocalDemo1 {

private static final ThreadLocal schemaLocal

= new ThreadLocal();

public void test1() {

String a = schemaLocal.get();

ThreadLocalDemo2 demo2 = new ThreadLocalDemo2();

demo2.test(a);

}

public static void main(String[] args) {

// TODO Auto-generated method stub

}

}

public class ThreadLocalDemo2 {

private static final ThreadLocal slocal = new ThreadLocal();

public void test(String b) {

String a = slocal.get();

// 其他代码

System.out.println(b);

}

public static void main(String[] args) {

// TODO Auto-generated method stub

}

}

public class TestMain {

public static void main(String[] args) {

// TODO Auto-generated method stub

ThreadLocalDemo1 d = new ThreadLocalDemo1();

d.test1();

}

}

一个线程调用 ThreadLocalDemo1 的 test1方法,在这个执行链中会涉及到两个ThreadLocal变量,调用ThreadLocal的get方法,首先会获取当前线程,然后从当前线程对象中获取线程内部属性[ThreadLocal.ThreadLocalMap threadLocals = null;],然后从ThreadLocalMap中以ThreadLocal对象为键,从threadLocals map中获取存放的值。

线程的threadLocals值为

{

ThreadLocalDemo1.schemaLocal  : 该变量中的值,

ThreadLocalDemo2.scloal : 存放在本线程中的值

}

3、 ThreadLocal优化思考

==================

ThreadLocal的数据访问算法,本质上就是Map的访问特性。

我在分析HashMap源码的时候,已经将HashMap的存储结构讲解完毕,如有兴趣,可以浏览一下我的博文:深入理解HashMap:http://blog.csdn.net/prestigeding/article/details/52861420,HashMap根据key的访问速度效率是很快的,为什么呢?因为HashMap根据key的hash,然后会定位到内部的数据槽(该数据是数组结构),众所周知,根据数组的下标访问,访问速度是最快的,也就是说HashMap根据key的定位速度比LinkedList等都快,仅次于数组访问方式,这是因为HashMap多了一步Hash定位槽的过程(当然,如果有Hash冲突那就更慢了)。所以,如果在高并发场景下,需要进一步优化ThreadLocal的访问性能,那就要从线程对象(Thread的threadLocals 数据结构下手了,如果能将数据结构修改为数组,然后每个ThreadLocal对象维护其下标那就完美了)。是的,Netty框架就是为了高并发而生的,由于并发访问的数量很大,一点点的性能优化,就会带来可观的性能提升效应,Netty主要从如下两个方面对ThreadLocal的实现进行优化

  • 线程对象直接提供 set、get方法,以便直接获取线程本地存储相关的变量属性。

  • 将数据存储基于数组存储。

4、Netty关于ThreadLocal机制的优化

=========================

由于ThreadLocal是JDK的原生实现,通用性很强,直接扩展进行定制化不是明智的选择,故Netty在优化ThreadLocal的方式是自己另起灶炉,实现ThreadLocal的语义。优化方法如下:

  • 提供一个接口,FastThreadLocalAccess,并对线程池工厂类进行定制,创建的线程继承在java.lang.Thread类,并实现FastThreadLocalAccess接口,提供直接设置,获取线程本地变量的方法。

  • 提供FastThreadLocal类,此类实现ThreadLocal相同的语义。

  • 提供InternalThreadLocalMap类,此类作用类同于java.lang.ThreadLocal.ThreadLocalMap类,用于线程存放真实数据的结构。

4.1 扩展线程对象,提供set,get方法


通过定制的线程池工厂,创建的线程对象为扩展后的线程对象,在Netty中对应为FastThreadLocalThread,该类本身很简单,值得大家注意的是其思想,jdk并发包中提供的线程池实现机制中,提供了线程创建的工厂的扩展点,这里就是其典型的实践。这里附上其源码,不做解读:

public class FastThreadLocalThread extends Thread implements FastThreadLocalAccess {

private InternalThreadLocalMap threadLocalMap;

public FastThreadLocalThread() { }

public FastThreadLocalThread(Runnable target) {

super(target);

}

public FastThreadLocalThread(ThreadGroup group, Runnable target) {

super(group, target);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

小编精心为大家准备了一手资料

以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术

【附】架构书籍

  1. BAT面试的20道高频数据库问题解析
  2. Java面试宝典
  3. Netty实战
  4. 算法

BATJ面试要点及Java架构师进阶资料

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值