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

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

 
    

多线程(八)~ThreadLocal、InheritableThreadLocal的使用的更多相关文章

  1. java 多线程 :ThreadLocal 共享变量多线程不同值方案;InheritableThreadLocal变量子线程中自定义值,孙线程可继承

      ThreadLocal类的使用 变量值的共享可以使用public static变量的形式,所有的线程都是用同一个public static变量.如果想实现每一个线程都有自己的值.该变量可通过Thr ...

  2. Java多线程:ThreadLocal

    一.ThreadLocal基础知识 ThreadLocal是线程的一个本地化对象,或者说是局部变量.当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的 ...

  3. 架构师养成记--6.单例和多线程、ThreadLocal

    一.ThreadLocal 使用wait/notify方式实现的线程安全,性能将受到很大影响.解决方案是用空间换时间,不用锁也能实现线程安全. 来看一个小例子,在线程内的set.get就是thread ...

  4. 【Python】[进程和线程]多进程,多线程,ThreadLocal,进程VS.线程,分布式进程

    1.多进程,multiprocessing模块,   进程间的通信:Queue[队列],Pipes[管子]2.多线程,    注意:线程公用变量,混乱   解决方法Lock:因为只有一个锁,所以当要执 ...

  5. Java多线程之 ThreadLocal

    一.什么是ThreadLocal? 顾名思义它是local variable(线程局部变量).它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副 ...

  6. 三十八 ThreadLocal

    在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁. 但是局部变量也有问题,就是在函数调用的 ...

  7. 并发和多线程(六)--ThreadLocal

    ThreadLocal是什么? 当使用ThreadLocal修饰变量的时候,ThreadLocal会为每个使用该变量的线程提供独立的变量副本,每个线程可以独立改变自己的副本,而不 影响其他线程的变量副 ...

  8. 14、Java并发性和多线程-Java ThreadLocal

    以下内容转自http://ifeve.com/java-theadlocal/: Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作.因此,尽管有两个线程同时执行一段相 ...

  9. java并发编程(九)ThreadLocal & InheritableThreadLocal

    参考文档: https://blog.csdn.net/u012834750/article/details/71646700 threadlocal内存泄漏:http://www.importnew ...

  10. Java多线程基础-ThreadLocal

    感谢原文作者:Yuicon 原文链接:https://segmentfault.com/a/1190000016705955 序 在多线程环境下,访问非线程安全的变量时必须进行线程同步,例如使用 sy ...

随机推荐

  1. HTML <form> target 属性

    浏览器支持 所有主流浏览器都支持 target 属性. 定义和用法 target 属性规定一个名称或一个关键词,指示在何处打开 action URL,即在何处显示提交表单后接收到的响应. target ...

  2. edX MITx: 6.00.1x Introduction to Computer Science and Programming Using Python 课程 Week 1: Python Basics Problem Set 1 Problem 3

    Assume s is a string of lower case characters. Write a program that prints the longest substring of  ...

  3. c++ 222

        [成功者的习惯]   1.背后说别人好话:听到某人说别人坏话时只微笑: 2.过去的事不全让人知道: 3. 尊敬不喜欢你的人:对事无情,对人有情: 4.多做自我批评:为别人喝彩: 5.感恩:学会 ...

  4. nginx+uwsgi+virtualenv+supervisor部署项目

    一.导论 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收请求,处理请求,响应请求) 基于wsgi运行的 ...

  5. poj3262

    一.题意:有n头牛,每头牛每分钟会吃D个菜,把这头牛赶回去需要时间T(人再返回又需要T),一次只能赶回去一头牛,也就是说剩下的牛会继续吃菜.求牛最少吃多少菜 二.思路:贪心.按D/T将牛进行排序,然后 ...

  6. 集成 Jenkins 和 TestNG 实现自助式自动化测试平台

    背景介绍 在软件业十分成熟的今天,敏捷(Agile)开发在业界日益流行,而面临的挑战也日益增多,不断变化的用户需求.缩短的开发周期.频繁的部署上线.复杂的产品架构和团队组织,如何继续保证软件的质量是一 ...

  7. Python中 字符串 转换为 字典

    需求:把以下字符串转换为字典 #字符串 testStr = '{ "pName": "Ceshi", "gender": 1, " ...

  8. Linux——【rpm、yun、源码包】安装

    RPM包或者安装源码包 在windows下安装一个软件很轻松,只要双击.exe的文件,安装提示连续“下一步”即可,然而linux系统下安装一个软件似乎并不那么轻松,因为我们不是在图形界面下.所以我们要 ...

  9. easyUI--datagrid 实现按键控制( enter tab 方向键 )

    1.表格定义时加上 onClickCell: onClickCell,2.定义列时加入编辑器3.引入 key.js 即可使用 enter 键 或者向下箭头 选中单元格下移 选中单元格上移 tab键 选 ...

  10. Ace向你推荐一些实用的干货库~开发安卓的好帮手

    1 毁灭地球的军火库arsenal- 你想要的枪这里都有卖 哈哈哈哈 , http://android-arsenal.com/ 2 黑科技---在线反编译----嘿嘿嘿  在线反编译 方便简单 客官 ...