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

滨海新区网站建设wordpress淘宝客开发

滨海新区网站建设,wordpress淘宝客开发,上海建站模板平台,ppt设计兼职Java并发编程中很重要的类#xff1a;ThreadLocal 在多线程应用程序中#xff0c;对共享变量进行读写的场景是很常见的。如果不使用一定的技术或方案#xff0c;会引发各种线程安全的问题。常见解决线程安全的方式有synchronized、volatile等方式#xff0c;但synchronized…Java并发编程中很重要的类ThreadLocal 在多线程应用程序中对共享变量进行读写的场景是很常见的。如果不使用一定的技术或方案会引发各种线程安全的问题。常见解决线程安全的方式有synchronized、volatile等方式但synchronized对性能的开销大volatile不能保证原子性所以这里介绍一个 解决多线程间共享变量的线程安全问题 的方法——ThreadLocal 1.什么是 ThreadLocal ThreadLocal 的作用可以实现在同一个线程数据共享, 从而解决多线程数据安全问题. ThreadLocal 可以给当前线程关联一个数据(普通变量、 对象、 数组)set 方法 [源码!] ThreadLocal 可以像 Map 一样存取数据 key 为当前线程, get 方法 每一个 ThreadLocal 对象只能为当前线程关联一个数据如果要为当前线程关联多个数 据 就需要使用多个 ThreadLocal对象实例 每个 ThreadLocal 对象实例定义的时候 一般为 static 类型 ThreadLocal 中保存数据 在线程销毁后 会自动释放 threadlocal时序图 2、ThreadLocal的作用 多线程访问同一个共享变量时特别容易出现并发问题特别是在多个线程需要对共享变量进行写入时。为了保证线程安全一般使用者在访问共享变量时需要进行适当的同步如图 1-3 所示 同步的措施一般是加锁但加锁会在一定程度上增加系统的复杂度以及影响系统的性能。 为了解决多线程间共享变量的线程安全ThreadLocal应运而生。 当创建一个ThreadLocal变量时访问这个变量的每个线程都有这个变量的一个本地副本当多个线程操作这个变量时实际上就是操作自己本地内存里面的变量从而避免了线程安全问题。图 1-3 就变成了 图1-4 如图 3,、Threadlocal的使用示例  public class ThreadLocalTest {private static ThreadLocalString threadLocal new ThreadLocal();public static void main(String[] args) {Thread thread1 new Thread(() - {threadLocal.set(threadLocal变量1);print(thread1);System.out.println(线程1的threadLocal变量的值为:threadLocal.get());});Thread thread2 new Thread(() - {threadLocal.set(threadLocal变量2);print(thread2);System.out.println(线程2的threadLocal变量的值为:threadLocal.get());});thread1.start();thread2.start();}public static void print(String s){System.out.println(s:threadLocal.get());} }上述代码中有一个 threadLocal 变量类型为ThreadLocal 然后创建了 thread1 和 thread2 并分别在两个线程中调用了 threadLocal.set(String str) 方法然后用 threadLocal.get() 方法去获取threadLocal变量的值。显然由输出结果可以知道线程 thread1 中获取到的值就是它给threadLocal设置的值即为本地变量1线程 thread2 中获取到的值就是它给threadLocal设置的值即为本地变量2。这两个线程是访问不到另外一个线程中的threadLocal的值的。 应用讲完了现在着重来看一下ThreadLocal的实现原理大厂面试必问~ 1、ThreadLocal 的 set、get方法 首先看下ThreadLocal 相关类的类图结构 再看一下Thraed里面的成员变量 我们可以发现Thread类中有两个类型为ThreadLocalMap的变量ThreadLoaclMap是一个定制化的HashMap。 在默认情况下每个线程中的这两个变量都为null ThreadLocal.ThreadLocalMap threadLocals null; ThreadLocal.ThreadLocalMap inheritableThreadLocals null; 只有当线程第一次调用ThreadLocal的set方法或get方法时才会创建它们。 public void set(T value) {//(1)获取当前线程Thread t Thread.currentThread();//(2)将当前线程作为key去查找对应的线程变量找到则设置。ThreadLocalMap map getMap(t);if (map ! null) {map.set(this, value);}else {//(3)第一次调用set方法时就创建当前线程对应的HashMap。createMap(t, value);}} (1)处代码首先获取调用set方法的线程然后使用当前线程作为参数调用getMap(t) 方法getMap(Thread t) 方法如下 ThreadLocalMap getMap(Thread t) {return t.threadLocals;} 可以看到getMap(t) 的作用是获取线程自己的变量 threadLocals 其类型是ThreadLocalMap。 如果getMap(t)的返回值非空则把value值存放到threadLocals中即把当前变量值存放入当前线程的成员变量threadLocals中。 threadLocals是一个HashMap结构其中key就是当前ThreadLocal的实例对象引用value是通过set方法传递的值。 void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue);} 如果getMap(t返回的是null则说明是第一次调 set 方法这时创建 当前线程的threadLocals 变量。 下面来看 createMap(t, value 干了啥 void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue);} 即创建了一个ThreadLocalMap对象并将当前线程的threadLocals引用执行它。 再来看看get()方法的代码实现 public T get() {//(4)获取当前线程Thread t Thread.currentThread();//(5)获取当前线程的threadLocals变量ThreadLocalMap map getMap(t);//(6)如果threadLocals不为null则返回对应的本地变量的值if (map ! null) {ThreadLocalMap.Entry e map.getEntry(this);if (e ! null) {SuppressWarnings(unchecked)T result (T)e.value;return result;}}//(7)threadLocals为空时则初始化当前线程的threadLocals成员变量return setInitialValue();}4处的代码首先获取当前线程实例如果当前线程的threadLocals不为null则直接返回当前线程绑定的本地变量否则执行7处代码进行初始化。setInitialValue() 方法如下private T setInitialValue() {//(8)初始化为nullT value initialValue();Thread t Thread.currentThread();ThreadLocalMap map getMap(t);//(9)如果当前线程的threadLocals变量不为空if (map ! null)map.set(this, value);else//(10)为空则创建一个ThreadLocalMap对象并将当前线程的threadLocals引用执行它。createMap(t, value);return value;}如果当前线程的threadLocals变量不为空则设置当前线程的本地变量值为null否则调用createMap方法创建ThreadLocalMap对象并将当前线程的threadLocals引用执行它。 总结下在每个线程里都有 threadLocals 的成员变量该变量的类型为ThreadLocalMap实际上可以理解为定制的HashMap其中key为我们所定义的ThreadLocal变量的this引用value则为set方法传递的值。每个线程的本地变量存放在线程自己的成员变量threadLocals中如果当前线程一直不消亡那么这些本地变量会一直存在故可能会造成内存溢出故使用完毕后需要使用 remove() 方法删除threadLocals中的本地变量。 2、Threadlocal 不支持继承性 首先看下下面代码 public class TestThreadLocal {//(1)创建线程变量public static ThreadLocalString threadLocal new ThreadLocal();public static void main(String[] args) {//(2)赋值本地变量threadLocal.set(hello world);//(3)启动子线程new Thread(() - {//(4)子线程输出线程变量的值System.out.println(子线程thread: threadLocal.get());}).start();//(5)主线程输出线程变量的值System.out.println(main线程: threadLocal.get());} } 输出结果说明同一个 ThreadLocal 变量在父线程中被设置值后在子线程中是获取不到的。 原因是子线程里面调用get方法时Thread t Thread.currentThread() 代码是获取当前线程当前线程是子线程而调用set方法给threadLocal赋值的线程是main两者是不同的线程故子线程调用get方法取得的threadLocal值为nullmain线程调用get方法取得的threadLocal值为“hello world”。 有没有方法让子线程能够访问到父线程中的值继续往下看啦。 3、lnheritableThreadLocal 类 为了解决让子线程能够访问到父线程中的值的问题lnheritableThreadLocal 应运而生。lnheritableThreadLocal 继承自 ThreadLocal并提供了一个新特性让子线程可以访问在父线程中设置的本地变量值。先来看下lnheritableThreadLocal 的实现 public class InheritableThreadLocalT extends ThreadLocalT {//(1)protected T childValue(T parentValue) {return parentValue;}//(2)ThreadLocalMap getMap(Thread t) {return t.inheritableThreadLocals;}//(3)void createMap(Thread t, T firstValue) {t.inheritableThreadLocals new ThreadLocalMap(this, firstValue);} }通过查看 InheritableThreadLocal 的源码可知lnheritableThreadLocal 继承了 ThreadLocal 类并重新了 childValue、getMap、createMap方法。 由3处代码可知InheritableThreadLocal 重写了 createMap 方法那么当第一次调用 InheritableThreadLocal 实例的set方法时创建的就是当前线程的inheritableThreadLocals变量的实例而不再是threadLocals了。 由2处代码可知InheritableThreadLocal 重写了 getMap 方法那么调用InheritableThreadLocal 实例的get方法时就是获取当前线程的inheritableThreadLocals变量的实例而不再是threadLocals。 那么1处代码是如何实现子线程可以访问在父线程中设置的本地变量值的 这要从创建Thread的代码将起打开Thread类的默认构造函数 public Thread(Runnable target) {init(null, target, Thread- nextThreadNum(), 0);} private void init(ThreadGroup g, Runnable target, String name,long stackSize) {init(g, target, name, stackSize, null, true); }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);}this.name name;//(4)获取当前线程Thread parent currentThread();SecurityManager security System.getSecurityManager();if (g null) {/* Determine if its an applet or not *//* If there is a security manager, ask the security managerwhat to do. */if (security ! null) {g security.getThreadGroup();}/* If the security doesnt have a strong opinion of the matteruse the parent thread group. */if (g null) {g parent.getThreadGroup();}}/* checkAccess regardless of whether or not threadgroup isexplicitly passed in. */g.checkAccess();/** Do we have the required permissions?*/if (security ! null) {if (isCCLOverridden(getClass())) {security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);}}g.addUnstarted();this.group g;this.daemon parent.isDaemon();this.priority parent.getPriority();if (security null || isCCLOverridden(parent.getClass()))this.contextClassLoader parent.getContextClassLoader();elsethis.contextClassLoader parent.contextClassLoader;this.inheritedAccessControlContext acc ! null ? acc : AccessController.getContext();this.target target;setPriority(priority);//(5)如果父线程的inheritableThreadLocals 变量不为nullif (inheritThreadLocals parent.inheritableThreadLocals ! null)//(6)设置子线程中的 inheritableThreadLocals 变量this.inheritableThreadLocals ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);/* Stash the specified stack size in case the VM cares */this.stackSize stackSize;/* Set thread ID */tid nextThreadID();} 由4处代码获取了当前线程main函数所在的线程即父线程 这里可能有同学会有疑问这里获取到的当前线程为何是父线程 想一下当我们new Thread()的时候是不是在main()方法里执行的所以当前执行创建Thread代码的线程是main线程所以4处代码中currentThread()方法获取到的就是父线程啦 由5处代码判断main线程里的inheritableThreadLocals 是否为null不为null时则执行代码6。 由6处代码我们来看看createInheritedMap()方法 static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {return new ThreadLocalMap(parentMap);} 在createInheritedMap方法中使用父线程的inheritableThreadLocals变量作为构造函数创建了一个新的ThreadLocalMap对象由6处:this.inheritableThreadLocalsThreadLocal.createInheritedMap(parent.inheritableThreadLocals); 知道将子线程的inheritableThreadLocals引用指向了这个新创建的ThreadLocalMap对象。 再看看 ThreadLocalMap(parentMap)构造函数 private ThreadLocalMap(ThreadLocalMap parentMap) {Entry[] parentTable parentMap.table;int len parentTable.length;setThreshold(len);table new Entry[len];for (int j 0; j len; j) {Entry e parentTable[j];if (e ! null) {SuppressWarnings(unchecked)ThreadLocalObject key (ThreadLocalObject) e.get();if (key ! null) {//(7)调用了InheritableThreadLocal类重写的 childValue 方法Object value key.childValue(e.value);Entry c new Entry(key, value);int h key.threadLocalHashCode (len - 1);while (table[h] ! null)h nextIndex(h, len);table[h] c;size;}}}} 在构造函数中就是把父线程的inheritableThreadLocal变量的值复制到新的ThreadLocalMap对象中7处代码实际上是调用了1处代码。 总结一下InheritableThreadLocal实现子线程可以访问父线程的线程变量的实现原理如下 InheritableThreadLocal通过重写createMap 和 getMap 方法让本地变量保存到了具体线程的inheritableThreadLocal变量中线程通过调用inheritableThreadLocal实例的set或get方法时就会创建当前线程的inheritableThreadLocal变量当父线程创建子线程时构造函数会把父线程中的inheritableThreadLocal变量里面的本地变量值复制一份保存到子线程的inheritableThreadLocal变量里 将最开始的代码作以下修改 public class TestThreadLocal {//(1)创建线程变量//public static ThreadLocalString threadLocal new ThreadLocal();//(1)创建线程变量public static InheritableThreadLocalString threadLocal new InheritableThreadLocal();public static void main(String[] args) {//(2)赋值本地变量threadLocal.set(hello world);//(3)启动子线程new Thread(() - {//(4)子线程输出线程变量的值System.out.println(子线程thread: threadLocal.get());}).start();//(5)主线程输出线程变量的值System.out.println(main线程: threadLocal.get());}}很多子线程需要使用父线程中的变量值的场景都可以使用InheritableThreadLocal是不是很强大呢 ThreadLocal、InheritableThreadLocal在Java并发编程中的地位举足轻重理解了它们的底层实现和应用场景会让你的大厂面试更有加分项
http://www.zqtcl.cn/news/752710/

相关文章:

  • 专业营销的网站建设公司哪家好专门做二手书的网站
  • 建新网站开发流程图电子商务网站开发综合实训报告
  • 临汾网站建设销售长沙网站建设1681989
  • 最近国内外重大新闻事件贺贵江seo教程
  • 网站开发源码网站运营建设方案
  • 网站建设公司 跨界鱼科技专业简述网站的制作步骤
  • 手机网站cms网站优化推广哪家好
  • 网站被k换域名qq空间 wordpress
  • 网站模板种类昆明cms建站模板
  • wordpress em企业网站做seo的优势
  • 设计师做私单网站全球最大的电商平台
  • 外贸联系网站wordpress 优惠券 插件
  • 公司网站开发费用兴田德润官方网站深圳百度快照优化
  • 做网站需要备案么行业网站策划
  • 去年做啥网站能致富周口seo推广
  • 主体负责人电话修改 网站备案什么样算网站需要备案
  • 网站建站免费空间外贸网站建设与优化
  • 网站极简设计建立网站基本知识
  • 网站建设管理标准wordpress rss采集
  • 乐清网站建设费用装修房子的app软件哪个好
  • 专业网站搭建运营工业网站素材
  • 建网站要会什么wordpress电影下载站
  • 济南设计网站的公司西安模板网站建设
  • 网站搜索功能如何实现网络培训学习心得体会
  • 网站设计方案书ppt网站展示型推广
  • 中国建设注册管理中心网站首页大连地区建设网站
  • 广州致峰网站建设藁城网络推广
  • 怎么做免费个人网站wordpress dux 5.3
  • 手机触屏版网站网站功能介绍
  • 商场设计案例青岛百度快速排名优化