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

阿里巴巴国际站下载电脑版网站建设竞标需要怎么做

阿里巴巴国际站下载电脑版,网站建设竞标需要怎么做,邮箱免费申请注册账号,医院管理系统目录 一、ThreadLocal类基本介绍 1.概述 : 2.作用及特定 : 二、ThreadLocal类源码解读 1.代码准备 : 1.1 图示 1.2 数据对象 1.3 测试类 1.4 运行测试 2.源码分析 : 2.1 set方法解读 2.2 get方法解读 一、ThreadLocal类基本介绍 1.概述 : (1) ThreadLocal,本…

目录

一、ThreadLocal类基本介绍

        1.概述 : 

        2.作用及特定 : 

二、ThreadLocal类源码解读

        1.代码准备 : 

            1.1 图示 

            1.2 数据对象

            1.3 测试类

            1.4 运行测试

        2.源码分析 : 

            2.1 set方法解读

            2.2 get方法解读


一、ThreadLocal类基本介绍

        1.概述 : 

        (1) ThreadLocal,本地线程变量,是Java中的一个类。ThreadLocal类提供了一种线程绑定机制,可以将状态与线程(Thread)关联起来。ThreadLocal类如下图所示 : 

        (2) 每个线程都会有自己独立的一个ThreadLocal变量,该变量对其他线程而言是封闭且隔离的,因此对该变量的读写操作只会影响到当前执行线程的这个变量,而不会影响到其他线程的同名变量

        2.作用及特定 : 

        (1) ThreadLocal可以实现在同一个线程数据共享,从而解决多线程数据安全问题。

        (2) 通过ThreadLocal类实例的set方法,可以为当前线程关联一个数据(变量,对象,数组)

        (3) 通过ThreadLocal类实例的get方法,可以像Map一样存取key-value键值对(其中key为当前线程),注意,显式的用法上与Map不相同

        (4) 每一个ThreadLocal对象,只能为当前线程关联一个数据,若想为当前线程关联多个数据,就需要使用到多个ThreadLocal实例

        (5) ThreadLocal实例往往定义为static类型。

        (6) ThreadLocal中保存的数据,会在线程销毁后自动释放


二、ThreadLocal类源码解读

        1.代码准备 : 

            1.1 图示 

                首先,我们要把代码打通,确保ThreadLocal对象可以在同一线程中实现数据共享。根据下图来定义所需要的测试类 : 

                在T1类,T1Service类,以及T2DAO类中分别打印出当前线程的名字,以及放入到threadLocal1对象中的数据对象,对比三个类打印出的线程名字和数据对象是否相同,即可验证“ThreadLocal可以实现在同一个线程数据共享”。

            1.2 数据对象

                定义Apple类和Grape类用作测试的数据对象。
                Apple类代码如下 : 

package threadlocal;public class Apple {
}

                Grape类代码如下 : 

package threadlocal;/*** @author : Cyan_RA9* @version : 21.0*/
public class Grape {
}

            1.3 测试类

                T1类代码如下 : 

package threadlocal;/*** @author : Cyan_RA9* @version : 21.0*/
public class T1 {//定义一个静态的ThreadLocal对象public static ThreadLocal<Object> threadLocal1 = new ThreadLocal<>();public static void main(String[] args) {//在主线程中启动一个新的子线程new Thread(new Task()).start();}public static class Task implements Runnable{@Overridepublic void run() {System.out.println("(Task)run方法,当前线程名 = " + Thread.currentThread().getName());Apple apple = new Apple();Grape grape = new Grape();//向threadLocal1对象中放入一个Apple对象System.out.println("(Task)run方法,放入的对象 = " + apple);threadLocal1.set(apple);new T1Service().test();}}
}

                T1Service类代码如下 : 

package threadlocal;/*** @author : Cyan_RA9* @version : 21.0*/
public class T1Service {public void test() {String name = Thread.currentThread().getName();System.out.println("(T1Service)当前线程名 =  " + name);Object o = T1.threadLocal1.get();System.out.println("(T1Service)得到的对象o = " + o);new T2DAO().test();}
}

                T2DAO类代码如下 : 

package threadlocal;/*** @author : Cyan_RA9* @version : 21.0*/
public class T2DAO {public void test() {String name = Thread.currentThread().getName();System.out.println("(T2DAO)当前线程名 = " + name);Object o = T1.threadLocal1.get();System.out.println("(T2DAO)得到的对象o = " + o);}
}

            1.4 运行测试

                运行结果 : 

        2.源码分析 : 

            2.1 set方法解读

                set方法源码如下 : 

    public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {map.set(this, value);} else {createMap(t, value);}}

                第一步,可以看到,set方法中首先就获取到了当前线程,而当前线程,就是调用set方法时——线程类run方法所在的那个线程;说明set方法和当前线程是关联的
                第二步通过当前线程对象获取到了ThreadLocalMap对象。此处的ThreadLocalMap,是ThreadLocal类的一个静态内部类。如下图所示 : 

                注意,为什么是通过当前线程对象来获取ThreadLocalMap对象呢?
                因为当前线程持有自己的ThreadLocal对象(该对象调用了set方法),而ThreadLocalMap又是ThreadLocal的一个内部类.
                
继续,接着判断得到的map对象是否为空,如下图所示 : 

                如果不为空,就将当前的ThreadLocal对象(this,即指在T1类中一开始调用set方法的ThreadLocal对象)和该对象调用set方法时放入的数据(value,此处是放入的Apple对象)。从这里也可以看出,如果同一个ThreadLocal对象再次调用set方法,会对存入的数据(value)进行替换——即"每一个ThreadLocal对象,只能为当前线程关联一个数据"。
                如果为空,就创建一个与当前线程对象关联的ThreadLocalMap对象,并将目标数据放入(value)。

                在set方法调用处设一个断点,进入Debug界面后可以看到当前线程对象名字,如下图所示 : 

                在this对象中向下找,可以找到一个threadLocals属性,发现它就是ThreadLocalMap类型,如下图所示 : 

                我们也可以Thread类的源码中找到这个属性,如下图所示 :

                而该属性下的table, 就是实际存放数据的地方(可以看到table是ThreadLocalMap的内部类Entry类型的数组)。当set方法执行完毕后,我们可以看到table数组中的Apple对象,如下图所示 :

                实际上,table就是线程用于管理ThreadLocal实例的容器
                而table数组中每个元素的referent属性(弱引用对象),也就是ThreadLocal对象,此处可以看到与之前一致,如下 : 

            2.2 get方法解读

                get方法源码如下 : (PS : 注意此处是泛型在方法上的应用,而不是自定义泛型方法)

    public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}

                第一步,和set方法一样,都是先得到当前的线程对象。为啥?因为只有得到了当前线程对象,才能找到它的属性threadLocals[ThreadLocal$ThreadLocalMap类型],继而找到该属性维护的table数组(ThreadLocal$ThreadLocalMap$Entry[]类型),然后根据当前线程持有的的ThreadLocal实例,找到数组中对应的Entry元素,继而拿到它的属性value(保存的数据)
                显然,get方法的源码中也的确是这么干的。通过当前线程对象拿到ThreadLocalMap对象,我们可以看一下getMap(t)的源码,如下图所示 :

                之后,判断map对象是否为空,如果不为空,就根据当前持有的ThreadLocal实例去找table数组中对应的Entry元素。继续往下走 : 

                拿到对应的Entry元素后,还要进行判断,如果该元素的确是存在的(表明当前的ThreadLocal实例已经为当前线程绑定过数据[一个value]), 就取出该Entry元素的value属性,此处为Object类型的apple对象,然后返回。

                🆗,以上就是对ThreadLocal的一些浅显解读。感谢阅读!

http://www.yayakq.cn/news/500210/

相关文章:

  • 政协网站建设要求深圳网站建设知名 乐云践新
  • 网站上的高清动态图怎么做的高校思政主题网站建设的意义
  • 生成静态网站宝安新桥h5网站建设步骤
  • 做基础网站主机要?vs2008如何新建网站
  • 个人求职网站html镇江网站制作价格
  • 德阳哪里有做网站的六安网站制作哪里有
  • 做暖暖的视频网站网页ui设计流程
  • 域名频道注册域名上海排名seo公司
  • 校园网站建设情况说明深圳市新房备案价查询官网
  • 网站备案的要求冬奥会网页设计代码
  • 网站排名首页前三位如何开通有赞微商城
  • 网站建设与维护是什么内容自己做网站 怎样下载模板
  • 东莞微网站建设公司山东东营市经济怎么样
  • 炒币网站开发seo网站搜索优化
  • app开发 网站建设hmm船公司网站
  • 网站设计行业吃香么游戏开发专业
  • 静态手机网站html博客网页完整代码
  • 菏泽公司做网站网站建设应考虑哪些方面的问题
  • 建设部执业注册网站网站页面怎么算
  • 嘉兴网站建设培训免费网站建设平台
  • 微信彩票网站网站建设房产网站制作模板
  • 做微网站多少钱河南艾特网站建设
  • 沈阳做机床的公司网站优化网站架构
  • 南山免费做网站公司排名东莞东坑网站设计
  • 做互联网需要网站吗什么网站建设
  • 网站收录下降长沙房产网站
  • 福州网站免费制作保定网站开发
  • 上海营销型网站建设平台直播网站app下载
  • 伴奏网站防盗是怎么做的外贸企业网站设计公司
  • 宁波网站建设与设计金字塔关键词优化需要从哪些方面开展