当前位置: 首页 > news >正文

单位网站建设方案高端品牌logo

单位网站建设方案,高端品牌logo,网站建设的经费预算,无货源电商选品软件JAVA重要知识点带着疑问看ThreadLocalGC 之后 key 是否为 null#xff1f;ThreadLocalMap Hash 算法ThreadLocalMap Hash 冲突ThreadLocalMap.set()方法ThreadLocalMap过期 key 的探测式清理流程ThreadLocalMap扩容机制ThreadLocalMap.get()详解ThreadLocalMap过期 key 的启发… JAVA重要知识点带着疑问看ThreadLocalGC 之后 key 是否为 nullThreadLocalMap Hash 算法ThreadLocalMap Hash 冲突ThreadLocalMap.set()方法ThreadLocalMap过期 key 的探测式清理流程ThreadLocalMap扩容机制ThreadLocalMap.get()详解ThreadLocalMap过期 key 的启发式清理流程InheritableThreadLocalThreadLocal项目实践带着疑问看 ThreadLocal的 key 是弱引用那么在 ThreadLocal.get()的时候发生GC之后key 是否为null ThreadLocal中ThreadLocalMap的数据结构 ThreadLocalMap的Hash 算法 ThreadLocalMap中Hash 冲突如何解决 ThreadLocalMap的扩容机制 ThreadLocalMap中过期 key 的清理机制 探测式清理和启发式清理流程 ThreadLocalMap.set()方法实现原理 ThreadLocalMap.get()方法实现原理 项目中ThreadLocal使用情况 ThreadLocal public class ThreadLocalTest {private ListString messages Lists.newArrayList();public static final ThreadLocalThreadLocalTest holder ThreadLocal.withInitial(ThreadLocalTest::new);public static void add(String message) {holder.get().messages.add(message);}public static ListString clear() {ListString messages holder.get().messages;holder.remove();System.out.println(size: holder.get().messages.size());return messages;}public static void main(String[] args) {ThreadLocalTest.add(TSES);System.out.println(holder.get().messages);ThreadLocalTest.clear();} } 打印如下 [SES] size: 0ThreadLocal对象可以提供线程局部变量每个线程Thread拥有一份自己的副本变量多个线程互不干扰。 Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量threadLocals也就是说每个线程有一个自己的ThreadLocalMap。ThreadLocalMap有自己的独立实现可以简单地将它的key视作ThreadLocalvalue为代码中放入的值实际上key并不是ThreadLocal本身而是它的一个弱引用。每个线程在往ThreadLocal里放值的时候都会往自己的ThreadLocalMap里存读也是以ThreadLocal作为引用在自己的map里找对应的key从而实现了线程隔离。 ThreadLocalMap有点类似HashMap的结构只是HashMap是由数组链表实现的而ThreadLocalMap中并没有链表结构。我们还要注意Entry 它的key是ThreadLocal? k 继承自WeakReference 也就是我们常说的弱引用类型。 GC 之后 key 是否为 null 补充Java的四种引用类型 强引用 new 出来的对象就是强引用类型只要强引用存在垃圾回收器将永远不会回收被引用的对象哪怕内存不足的时候 软引用使用 SoftReference 修饰的对象被称为软引用软引用指向的对象在内存要溢出的时候被回收 弱引用使用 WeakReference 修饰的对象被称为弱引用只要发生垃圾回收若这个对象只被弱引用指向那么就会被回收 虚引用虚引用是最弱的引用在 Java 中使用 PhantomReference 进行定义。虚引用中唯一的作用就是用队列接收对象即将死亡的通知 如果强引用不存在的话那么 key 就会被回收也就是会出现 value 没被回收key 被回收导致 value 永远存在出现内存泄漏。 ThreadLocal.set()方法源码如下主要是判断ThreadLocalMap是否存在然后使用ThreadLocal中的set方法进行数据处理。 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null)map.set(this, value);elsecreateMap(t, value); }void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue); }ThreadLocalMap Hash 算法 ThreadLocalMap当然也要实现自己的hash算法来解决散列表数组冲突问题。 int i key.threadLocalHashCode (len-1); ThreadLocalMap中hash算法很简单这里i就是当前 key 在散列表中对应的数组下标位置。 threadLocalHashCode值的计算ThreadLocal中有一个属性为HASH_INCREMENT 0x61c88647 public class ThreadLocalT {private final int threadLocalHashCode nextHashCode();private static AtomicInteger nextHashCode new AtomicInteger();private static final int HASH_INCREMENT 0x61c88647;private static int nextHashCode() {return nextHashCode.getAndAdd(HASH_INCREMENT);}static class ThreadLocalMap {ThreadLocalMap(ThreadLocal? firstKey, Object firstValue) {table new Entry[INITIAL_CAPACITY];int i firstKey.threadLocalHashCode (INITIAL_CAPACITY - 1);table[i] new Entry(firstKey, firstValue);size 1;setThreshold(INITIAL_CAPACITY);}} } 每当创建一个ThreadLocal对象这个ThreadLocal.nextHashCode 这个值就会增长 0x61c88647 。这个值很特殊它是斐波那契数 也叫 黄金分割数。hash增量为 这个数字带来的好处就是 hash 分布非常均匀。 ThreadLocalMap Hash 冲突 虽然ThreadLocalMap中使用了黄金分割数来作为hash计算因子大大减少了Hash冲突的概率但是仍然会存在冲突。HashMap中解决冲突的方法是在数组上构造一个链表结构冲突的数据挂载到链表上如果链表长度超过一定数量则会转化成红黑树。而 ThreadLocalMap 中并没有链表结构所以这里不能使用 HashMap 解决冲突的方式了。 ThreadLocalMap.set()方法 往ThreadLocalMap中set数据新增或者更新数据分为好几种情况 第一种情况 通过hash计算后的槽位对应的Entry数据为空 直接将数据放到该槽位第二种情况 槽位数据不为空key值与当前ThreadLocal通过hash计算获取的key值一致 直接更新该槽位的数据第三种情况 槽位数据不为空往后遍历过程中在找到Entry为null的槽位之前没有遇到key过期的Entry 遍历散列数组线性往后查找如果找到Entry为null的槽位则将数据放入该槽位中或者往后遍历过程中遇到了key 值相等的数据直接更新即可。槽位数据不为空往后遍历过程中在找到Entry为null的槽位之前遇到key过期的Entry即keynull Entry数据key为null表明此数据key值已经被垃圾回收掉了此时就会执行replaceStaleEntry()方法该方法含义是替换过期数据的逻辑以index作为起点开始遍历进行探测式数据清理工作。 向前迭代查找for循环迭代直到碰到Entry为null第一个槽位结束。 向后迭代如果找到了相同 key 值的 Entry 数据。更新Entry的值并交换staleSlot元素位置。向后遍历过程中如果没有找到相同 key 值的 Entry 数据就直到Entry为null停止寻找。 清理工作主要是有两个方法expungeStaleEntry()和cleanSomeSlots() ThreadLocalMap过期 key 的探测式清理流程 expungeStaleEntry方法遍历散列数组从开始位置向后探测清理过期数据将过期数据的Entry设置为null沿途中碰到未过期的数据则将此数据rehash后重新在table数组中定位如果定位的位置已经有了数据则会将未过期的数据放到最靠近此位置的Entrynull的桶中使rehash后的Entry数据距离正确的桶的位置更近一些 ThreadLocalMap扩容机制 在ThreadLocalMap.set()方法的最后如果执行完启发式清理工作后未清理到任何数据且当前散列数组中Entry的数量已经达到了列表的扩容阈值(len*2/3)就开始执行rehash()逻辑 rehash()具体实现 private void rehash() {expungeStaleEntries();if (size threshold - threshold / 4)resize(); }private void expungeStaleEntries() {Entry[] tab table;int len tab.length;for (int j 0; j len; j) {Entry e tab[j];if (e ! null e.get() null)expungeStaleEntry(j);} }清理完成之后table中可能有一些key为null的Entry数据被清理掉所以此时通过判断size threshold - threshold / 4 也就是size threshold * 3/4 来决定是否扩容。 ThreadLocalMap.get()详解 第一种情况 通过查找key值计算出散列表中slot位置然后该slot位置中的Entry.key和查找的key一致 直接返回第二种情况 slot位置中的Entry.key和要查找的key不一致 需要继续往后迭代查找。 如果向后Entry.keynull触发一次探测式数据回收操作执行expungeStaleEntry()方法执行完后index 的key为空的数据都会被回收而index 不为空的数据都会前移 源码如下java.lang.ThreadLocal.ThreadLocalMap.getEntry(): private Entry getEntry(ThreadLocal? key) {int i key.threadLocalHashCode (table.length - 1);Entry e table[i];if (e ! null e.get() key)return e;elsereturn getEntryAfterMiss(key, i, e); }private Entry getEntryAfterMiss(ThreadLocal? key, int i, Entry e) {Entry[] tab table;int len tab.length;while (e ! null) {ThreadLocal? k e.get();if (k key)return e;if (k null)expungeStaleEntry(i);elsei nextIndex(i, len);e tab[i];}return null; }ThreadLocalMap过期 key 的启发式清理流程 探测式清理是以当前Entry 往后清理遇到值为null则结束清理属于线性探测清理。 在添加新元素或删除另一个陈旧元素时调用。它执行对数次扫描循环 log2n次如果在循环中发现了 过期key此时会进行探测式清理并重置循环次数为 log2n次 InheritableThreadLocal 使用ThreadLocal的时候在异步场景下是无法给子线程共享父线程中创建的线程副本数据的 JDK 中还有一个InheritableThreadLocal类可以解决该问题 public class InheritableThreadLocalDemo {public static void main(String[] args) {ThreadLocalString ThreadLocal new ThreadLocal();ThreadLocalString inheritableThreadLocal new InheritableThreadLocal();ThreadLocal.set(父类数据:threadLocal);inheritableThreadLocal.set(父类数据:inheritableThreadLocal);new Thread(new Runnable() {Overridepublic void run() {System.out.println(子线程获取父类ThreadLocal数据 ThreadLocal.get());System.out.println(子线程获取父类inheritableThreadLocal数据 inheritableThreadLocal.get());}}).start();} } 打印 子线程获取父类ThreadLocal数据null 子线程获取父类inheritableThreadLocal数据父类数据:inheritableThreadLocal inheritableThreadLocal的实现原理 子线程是通过在父线程中通过调用new Thread()方法来创建子线程Thread#init方法在Thread的构造方法中被调用。在init方法中拷贝父线程数据到子线程中 private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {if (name null) {throw new NullPointerException(name cannot be null);}if (inheritThreadLocals parent.inheritableThreadLocals ! null)this.inheritableThreadLocals ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);this.stackSize stackSize;tid nextThreadID(); } InheritableThreadLocal仍然有缺陷一般做异步化处理都是使用的线程池而InheritableThreadLocal是在new Thread中的init()方法给赋值的而线程池是线程复用的逻辑所以这里会存在问题。当然有问题出现就会有解决问题的方案阿里巴巴开源了一个TransmittableThreadLocal组件就可以解决这个问题 ThreadLocal项目实践 现在都是分布式系统统一对外提供服务项目间调用的关系可以通过 traceId 来关联。不同项目之间传递 traceId 通过org.slf4j.MDC实现内部通过ThreadLocal实现 当前端发送请求到服务 A时服务 A会生成一个类似UUID的traceId字符串将此字符串放入当前线程的ThreadLocal中在调用服务 B的时候将traceId写入到请求的Header中服务 B在接收请求时会先判断请求的Header中是否有traceId如果存在则写入自己线程的ThreadLocal中。
http://www.yingshimen.cn/news/95387/

相关文章:

  • 漳州做网站wordpress文章表情
  • 商务网站建设步骤有几个网站建设总费用
  • 有哪些站内推广的方式广州市建筑股份有限公司
  • 单页网站 html5 动态自己做网站到哪里去接广告
  • 建立一个网站赚钱了东莞网站排名优化seo
  • 聊城哪里做网站网站平台搭建包括哪些
  • 网站跟域名备案数量小公司根本办不了icp许可证
  • 常德建设企业网站室内装修哪家好
  • 浙江创新网站建设销售wordpress slider教程
  • html5制作网站开发seo网站设计工具
  • wordpress建站图片效果企业做网站都需要准备哪些材料
  • 建设网站的目的和功能定位seo页面链接优化
  • 化肥网站模板网站搭建技术
  • 潼南集团网站建设游戏网站规划方案
  • 建设网站服务器自营方式的特点站点建设网站
  • 手机网站建设深圳python语言属于什么语言
  • 图片模板 网站源码外贸网站增加权重
  • 温州专业网站制作设计项目网格化管理方案
  • 美食网站是怎么做的深圳网站开发费用
  • 网站建设需要什么呢wordpress 主题 500
  • 中国建设银行官方网站诚聘英才频道物联网平台层的主要功能
  • 深圳设计网站的公司中国品牌策划公司排名
  • 学建站论坛line 设计网站
  • 青岛哪家公司做网站好百度销售
  • 定制网站哪家好html框架做网站
  • 网站换空间 sitewordpress留言板页面怎么制作
  • 建个企业网站有什么用百度做玻璃钢的网站
  • 珠宝销售网站源码站长统计app软件大全
  • 地方网站商城怎么做大丰城乡建设局网站
  • 做地方旅游网站目的意义英文网站建设 深圳