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

温州哪里做网站比较好/站长统计app软件下载官网

温州哪里做网站比较好,站长统计app软件下载官网,做家政网站,什么网站做家具外贸好呢ThreadLocal原理 阅读本文章之前,需要先了解Java中强软弱虚的概念,传送地址:Java中强软弱虚四种引用 文章目录ThreadLocal原理一、介绍二、快速入门三、ThreadLocal与synchronized的区别四、ThreadLocal内部结构五、ThreadLocal核心方法源码…

ThreadLocal原理

阅读本文章之前,需要先了解Java中强软弱虚的概念,传送地址:Java中强软弱虚四种引用

文章目录

  • ThreadLocal原理
    • 一、介绍
    • 二、快速入门
    • 三、ThreadLocal与synchronized的区别
    • 四、ThreadLocal内部结构
    • 五、ThreadLocal核心方法源码
      • 1. set方法
      • 2. get方法
    • 六、弱引用的使用
      • 1. 为什么要使用弱引用?
      • 2. 使用弱引用后是否依然存在内存泄漏?
      • 3. 线程池归还线程必须清理Map

一、介绍

  • 可以解决多线程的数据安全问题,将当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合等)
  • 每个线程只能存取本线程的数据,无法操作其他线程的数据,各个线程的数据互相独立
  • ThreadLocal中定义了 set、get、remove 方法,用来关联 / 取出 / 移除数据
  • 每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个ThreadLocal 对象实例

二、快速入门

public class ThreadLocalTest {public static void main(String[] args) throws InterruptedException {//创建ThreadLocal对象实例final ThreadLocal<Integer> th = new ThreadLocal<Integer>();//t1线程new Thread(new Runnable() {@Overridepublic void run() {try {th.set(100); //t1线程存放数据System.out.println("t1线程赋予的值:" + th.get());Thread.sleep(2000); //t1线程睡眠2秒,睡眠的时间段内t2线程会运行System.out.println("t1线程获取的值:"+th.get());} catch (InterruptedException e) {e.printStackTrace();}}}).start();Thread.sleep(1000);//t2线程new Thread(new Runnable() {@Overridepublic void run() {Integer ele = th.get(); //t2线程取出数据(此时为null,与t1无关系)System.out.println("t2线程获取的值:" + ele);th.set(200); //t2线程赋值System.out.println("t2线程赋值后获取的值:"+th.get()); //t2线程从自己的副本中获取值}}).start();}
}

运行结果:

image-20210721171230454

三、ThreadLocal与synchronized的区别

  • 原理不同
    • synchronized
      • 只提供了一份数据,让不同的线程竞争锁访问
    • ThreadLocal
      • 为每一个线程都提供了各自的数据,从而实现同时访问互不干扰
  • 侧重点不同
    • synchronized
      • 多个线程之间访问资源的同步
    • ThreadLocal
      • 多线程中让每个线程之间的数据相互隔离

四、ThreadLocal内部结构

  • 每个 Thread 维护一个 ThreadLocalMap,这个Map的 keyThreadLocal 实例本身,value 是真正要存储的值

    image-20210721171604754
  • 图示

    image-20210721191903457

    Map由Entry键值对组成

    Thread销毁之后,对应的ThreadLocalMap也会随之销毁,能减少内存的使用

五、ThreadLocal核心方法源码

1. set方法

  • 源码和对应的中文注释

    /*** 参数是Map中的value值*/
    public void set(T value) {// 获取当前线程对象Thread t = Thread.currentThread();// 获取此线程对象中维护的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 判断map是否存在if (map != null)// 存在则调用set方法,this表示此线程中TheadLocal实例// 创建Entry并赋值map.set(this, value);else// 如果当前线程不存在ThreadLocalMap对象,则创建MapcreateMap(t, value);
    }/*** 被调用的getMap方法* @param 当前线程* @return 对应维护的ThreadLocalMap */
    ThreadLocalMap getMap(Thread t) {return t.threadLocals;
    }/*** 被调用的createMap方法* @param 当前线程* @param 存放到Map中的第一个entry的值*/
    void createMap(Thread t, T firstValue) {//this是ThreadLocal实例t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
    
  • 代码执行流程

    • 首先获取当前线程,并根据当前线程获取一个Map
    • 如果获取的Map不为空,则将参数设置到Map中(当前ThreadLocal的引用作为key),创建Entry并赋值
    • 如果Map为空,则给该线程创建Map,并设置初始值,初始值即为参数值

2. get方法

  • 源码和对应的中文注释

    /*** 返回当前线程的Map中的value值*/
    public T get() {// 获取当前线程对象Thread t = Thread.currentThread();// 获取此线程对象中维护的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果此map存在if (map != null) {// 以当前的ThreadLocal为key,调用getEntry获取对应的EntryThreadLocalMap.Entry e = map.getEntry(this);// 如果Entry不为空,返回对应的value值if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}//有两种情况执行setInitialValue()方法//第一种情况: map不存在,表示此线程没有维护ThreadLocalMap对象//第二种情况: map存在, 但是没有与当前ThreadLocal关联的entryreturn setInitialValue();
    }/*** 被调用的setInitialValue方法,创建Entry并返回对应的value值,默认为null*/
    private T setInitialValue() {// 调用initialValue获取初始化的值// 此方法可以被子类重写, 如果不重写默认返回nullT value = initialValue();// 获取当前线程对象Thread t = Thread.currentThread();// 获取此线程对象中维护的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 判断map是否存在if (map != null)// 存在则调用map.set设置此实体entrymap.set(this, value);else// 1.当前线程Thread不存在ThreadLocalMap对象// 2.则调用createMap进行ThreadLocalMap对象的初始化// 3.并将t(当前线程)和value(默认为null)作为第一个entry存放至ThreadLocalMap中createMap(t, value);// 返回设置的值value,默认为nullreturn value;
    }
  • 代码执行流程

    • 首先获取当前线程, 根据当前线程获取一个Map
    • 如果获取的 Map 不为空,则在Map中以 ThreadLocal 的引用作为key在Map中获取对应的 Entry e
    • 如果 e 不为空,则返回 e.value
    • 如果Map为空或者e为空,则通过 initialValue() 函数获取初始值 value(默认为null),然后用ThreadLocal的引用和value作为 firstKey 和 firstValue 创建一个新的 Map
  • 总结: 先获取当前线程的 ThreadLocalMap 变量,如果存在则返回值,不存在则创建并返回初始值。

六、弱引用的使用

Entry对应的源码如下:

//Entry继承自一个弱引用
static class Entry extends WeakReference<ThreadLocal<?>> {//属性valueObject value;//构造器Entry(ThreadLocal<?> k, Object v) {super(k); //父类会创建一个弱引用,参数是ThreadLocal对象value = v;}
}//被调用的父类方法
public WeakReference(T referent) {super(referent);
}//被调用的父类方法,第二个参数引用队列传递null值
Reference(T referent, ReferenceQueue<? super T> queue) {this.referent = referent;this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}

通过上述源码得知,创建Entry的时候会创建一个弱引用,并指向当前线程的ThreadLocal对象,如下图所示:

image-20210721184813095

1. 为什么要使用弱引用?

如果Entry中的key使用强引用指向ThreadLocal对象,当ThreadLocal实例 threadLocal = null; 时,由于ThreadLocal对象仍然被Entry中的key强引用,所以ThreadLocal对象不会被垃圾回收,存在内存泄漏。

内存泄漏:对象不会被GC所回收,然而它却占用内存。

如果使用弱引用,当垃圾回收时,ThreadLocal对象被回收,可以解决ThreadLocal对象内存泄漏的问题。

2. 使用弱引用后是否依然存在内存泄漏?

当ThreadLocal对象被回收后,Entry中的key为null,无法获取value的值,无法回收,所以value指向的内存空间仍然存在内存泄漏问题,故应该使用 remove() 方法将此条Entry记录删除。

3. 线程池归还线程必须清理Map

如果线程池中的线程归还时,没有清理ThreadLocalMap,则此线程被再次使用的时候,可能会导致Map中的数据发生错误,比如发现Map中已经有同名的key,则不会再插入新值等情况。

http://www.lbrq.cn/news/1117369.html

相关文章:

  • 切削工具东莞网站建设/线上推广活动有哪些
  • 网站seo具体怎么做/windows优化大师在哪里
  • 网站忘记备案/百度网页版下载
  • 你愿意做我女朋友吗表白网站/中国国家培训网官网查询
  • 赞助网站怎么做/郑州今日重大新闻
  • 网站循环滚动图片z怎么做/百度游戏客服在线咨询
  • 网站开发项目外包/简单的网站建设
  • 网页美工培训学校/武汉seo 网络推广
  • 网站风格设计原则/百度关键词价格查询软件
  • 网站设计与建设论文/yahoo搜索引擎
  • 图表统计类手机网站开发/全网整合营销平台
  • 百度搜索自己的网站/360建站和凡科哪个好
  • 长春做网站的/友情链接联盟
  • 公司做网站,要准备哪些素材/国外网站
  • 河东做网站公司/需要一个网站
  • 网站建设 话术/b站是哪个网站
  • 整站下载器 做网站地图/中视频自媒体平台注册
  • 怎么弄百度网站/2024年重大新闻简短
  • 怎么做网站程序/常用的搜索引擎有哪些?
  • 改变WordPress界面/seodao cn
  • 做那种的视频网站有哪些/网络营销模式有哪些
  • 新闻网站建设条件/seo站长工具查询
  • 音乐网站开发 群/在百度上怎么发布信息
  • 专门做企业名录的网站/信阳seo公司
  • 网站做实名认证/专业北京网站建设公司
  • 网站建设平台流程/seo推广方案怎么做
  • 模板网站robots怎么做/太原百度推广开户
  • 电子政务政府门户网站建设方案/廊坊关键词排名首页
  • wordpress 多域名绑定/北京seo优化诊断
  • wordpress收费下载/成都网站快速优化排名
  • xss-lab1-8关
  • JavaScript进阶篇——第五章 对象成员管理与数组遍历优化
  • GitHub Pages+Jekyll 静态网站搭建(二)
  • 2025最新国产用例管理工具评测:Gitee Test、禅道、蓝凌测试、TestOps 哪家更懂研发协同?
  • 【卡尔曼滤波第六期】集合变换卡尔曼滤波 ETKF
  • SELinux 详细解析