多线程(八)~ThreadLocal、InheritableThreadLocal的使用

mac2022-06-30  99

    通过前面的学习,我们了解了在多线程+成员变量等情况下会出现线程安全的问题。那么解决线程安全问题除了使用synchronize关键字之外,还有另一种常用的解决思路,那就是使用ThreadLocal类,下面我们会对这个类做一下简介并指出两者的差异。

      ThreadLocal:通过字面翻译过来意思是“线程本地”,代表线程自己的本地变量。在多线程环境下,所有线程会共享类中的成员变量,那么这种情况下有可能会引发线程安全的问题。如果线程有自己的本地变量是不是就不会冲突了,ThreadLocal的原理就是这样,为线程创建自己的本地变量,多个线程间不共享。       线程本地变量最初始是空值null,最最常用的方法就是get()、set(Object value),其实这些值是维护在一个 ThreadLocalMap中的。   简单的get()、set()的demo: package com.multiThread.test.mythreadlocal;publicclassSampleTest{//线程本地变量publicstaticThreadLocal tl =newThreadLocal();publicstaticvoid main(String[] args){if(tl.get()==null){System.out.println("线程初始变量是空值"); tl.set("我的值");}System.out.println(tl.get());System.out.println(tl.get());}}   线程变量的隔离性(非共享) 线程本地变量工具类: package com.multiThread.util;publicclassThreadLocalUtil{publicstaticfinalThreadLocal<String> tl =newThreadLocal<String>();} 线程类: package com.multiThread.thread;import com.multiThread.util.ThreadLocalUtil;publicclassMyThreadLocalAimplementsRunnable{@Overridepublicvoid run(){for(int i =0;i<100;i++){ThreadLocalUtil.tl.set("ThreadA:"+(i +1));System.out.println("ThreadA:"+ThreadLocalUtil.tl.get());try{Thread.sleep(20);}catch(InterruptedException e){ e.printStackTrace();}}}} package com.multiThread.thread;import com.multiThread.util.ThreadLocalUtil;publicclassMyThreadLocalBimplementsRunnable{@Overridepublicvoid run(){for(int i =0;i<100;i++){ThreadLocalUtil.tl.set("ThreadB:"+(i +1));System.out.println("ThreadB:"+ThreadLocalUtil.tl.get());try{Thread.sleep(20);}catch(InterruptedException e){ e.printStackTrace();}}}} 测试类: package com.multiThread.test.mythreadlocal;import com.multiThread.thread.MyThreadLocalA;import com.multiThread.thread.MyThreadLocalB;publicclassMyThreadRun{publicstaticvoid main(String[] args){MyThreadLocalA myThreadLocalA =newMyThreadLocalA();MyThreadLocalB myThreadLocalB =newMyThreadLocalB();Thread t1 =newThread(myThreadLocalA);Thread t2 =newThread(myThreadLocalB); t1.start(); t2.start();}} 测试结果: ...ThreadB:ThreadB:95ThreadA:ThreadA:95ThreadB:ThreadB:96ThreadA:ThreadA:96ThreadB:ThreadB:97ThreadA:ThreadA:97ThreadA:ThreadA:98ThreadB:ThreadB:98ThreadB:ThreadB:99ThreadA:ThreadA:99ThreadB:ThreadB:100ThreadA:ThreadA:100 通过结果可以看出线程A和线程B之间的变量并非共享的,线程本地变量具有隔离性,只是自己用的。   为线程本地变量初始化值:     继承自ThreadLocal类,并实现initialValue(),设置返回值即可。 publicstaticfinalThreadLocal myLocal =newThreadLocal(){protectedObject initialValue(){return250;};}; System.out.println("默认值为:" + TicketThread.myLocal.get()); 默认值为:250   InheritableThreadLocal可以使子线程能从父线程中获取本地变量的值,例如: 子线程类: package com.wang.threadlocal;publicclassPersonimplementsRunnable{@Overridepublicvoid run(){System.out.println("从父线程中获取线程变量:"+MyInheritableThradLocal.threadLocal.get());}}   测试类: package com.wang.threadlocal;publicclassInheritableTest{publicstaticvoid main(String[] args){MyInheritableThradLocal.threadLocal.set("who let the dogs out?");System.out.println("Main线程中的值为:"+MyInheritableThradLocal.threadLocal.get());Person person =newPerson();Thread t1 =newThread(person); t1.start();}} 从例子中可以看出,在main线程中设置的线程本地变量,在子线程中也能拿到。 注意:若子线程获取值的同时,父线程对线程本地变量值做了修改,则子线程取到的值还是原值。           

来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/douJiangYouTiao888/p/6473818.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)