ThreadLocal的疑问?

问题描述

贴上代码:classAccount{/*定义一个ThreadLocal类型的变量,该变量将是一个线程局部变量每个线程都会保留该变量的一个副本*/privateThreadLocal<String>name=newThreadLocal<String>();//定义一个初始化name属性的构造器publicAccount(Stringstr){this.name.set(str);//下面代码用于访问当前线程的name副本的值System.out.println("---"+this.name.get());}//name的setter和getter方法publicStringgetName(){returnname.get();}publicvoidsetName(Stringstr){this.name.set(str);}}classMyTestextendsThread{//定义一个Account属性privateAccountaccount;publicMyTest(Accountaccount,Stringname){super(name);this.account=account;}publicvoidrun(){//循环10次for(inti=0;i<10;i++){//当i==6时输出将账户名替换成当前线程名if(i==6){account.setName(getName());}//输出同一个账户的账户名和循环变量System.out.println(account.getName()+"账户的i值:"+i);}}}publicclassThreadLocalTest{publicstaticvoidmain(String[]args){//启动两条线程,两条线程共享同一个AccountAccountat=newAccount("初始名");/*虽然两条线程共享同一个账户,即只有一个账户名但由于账户名是ThreadLocal类型的,所以每条线程都完全拥有各自的账户名副本,所以从i==6之后,将看到两条线程访问同一个账户时看到不同的账户名。*/newMyTest(at,"线程甲").start();newMyTest(at,"线程乙").start();}}

运行后控制台输出:我的困惑是:为什么在i变为6之前,account.getName()的输出为null?主线程启动的两个线程的构造器里都传入了at,那么,这个account.getName()为什么不输出为“初始名”呢,不是副本吗,副本应该和本体一样才对啊?求高人讲解。。。

解决方案

本帖最后由 fangmingshijie 于 2014-04-02 09:04:52 编辑
解决方案二:
在6之前你没有将name保存到线程的account对象里
解决方案三:
不好意思,看错了,感觉对了啊
解决方案四:
基本上原因就是ThreadLocal中set的对象只能为本线程所看见,不能被其他线程看见对于上面的代码,Account实例化时,成员name.set()的对象只能被main线程取出,而后面的线程甲、乙并不能获取到该Account对象的成员name中set的对象,所以并不会有什么name中存放对象的副本什么的。
解决方案五:
否则如果能看见这个被set的对象,就意味着甲乙线程能看见这个对象的引用,那么当修改对象时,就不能实现甲乙分别设置了一个name,这与ThreadLocal的设计是违背的。
解决方案六:
引用3楼java_liyi的回复:

基本上原因就是ThreadLocal中set的对象只能为本线程所看见,不能被其他线程看见对于上面的代码,Account实例化时,成员name.set()的对象只能被main线程取出,而后面的线程甲、乙并不能获取到该Account对象的成员name中set的对象,所以并不会有什么name中存放对象的副本什么的。

+1
解决方案七:
toptoptop
解决方案八:
引用5楼lq83205823的回复:

Quote: 引用3楼java_liyi的回复:
基本上原因就是ThreadLocal中set的对象只能为本线程所看见,不能被其他线程看见对于上面的代码,Account实例化时,成员name.set()的对象只能被main线程取出,而后面的线程甲、乙并不能获取到该Account对象的成员name中set的对象,所以并不会有什么name中存放对象的副本什么的。

+1

我试验过,绝对正解
解决方案九:
三楼是对的threadlocal奥妙在此
解决方案十:
ThreadLocal可以理解为一个Map<Thread_ID,Value>,实例化Account时相当于Map.put(主线程_Id,"初始名");线程甲启动后,在循环输出中name.getName相当于returnMap.get(线程甲_Id),故返回值为null。希望可以帮到你
解决方案十一:
什么情景下使用ThreadLocal比较好?什么情景下使用同步比较好啊?
解决方案十二:
publicTget()返回此线程局部变量的当前线程副本中的值。如果变量没有用于当前线程的值,则先将其初始化为调用initialValue()方法返回的值。返回此线程局部变量的当前线程的“初始值”。线程第一次使用get()方法访问变量时将调用此方法,但如果线程之前调用了set(T)方法,则不会对该线程再调用initialValue方法。通常,此方法对每个线程最多调用一次,但如果在调用get()后又调用了remove(),则可能再次调用此方法。该实现返回null;如果程序员希望线程局部变量具有null以外的值,则必须为ThreadLocal创建子类,并重写此方法。通常将使用匿名内部类完成此操作。
解决方案十三:
引用11楼huanongying131的回复:

publicTget()返回此线程局部变量的当前线程副本中的值。如果变量没有用于当前线程的值,则先将其初始化为调用initialValue()方法返回的值。返回此线程局部变量的当前线程的“初始值”。线程第一次使用get()方法访问变量时将调用此方法,但如果线程之前调用了set(T)方法,则不会对该线程再调用initialValue方法。通常,此方法对每个线程最多调用一次,但如果在调用get()后又调用了remove(),则可能再次调用此方法。该实现返回null;如果程序员希望线程局部变量具有null以外的值,则必须为ThreadLocal创建子类,并重写此方法。通常将使用匿名内部类完成此操作。

+1创建匿名内部类覆盖它的initialValue()方法返回一个默认值就好了,只要你觉得有默认值是设计要求的就可以这么做,多数时候并不需要默认值。

时间: 2024-09-22 20:44:58

ThreadLocal的疑问?的相关文章

关于Java ThreadLocal的疑问

问题描述 ThreadLocal作为一个可以将数据进行线程隔离的解决方法,其本质还是将数据存放在各个线程对象中(数据存放在Thread的ThreadLocalMap threadLocals中):那么为什么JDK不在设计的时候就使Thread对象具有保存线程上下文的能力呢?比如可以这样:public class Thread{...private Map<Object,Object> contexts = new WeakHashMap<Object,Object>();publi

关于ThreadLocal解决哲学家就餐问题的疑问

问题描述 众所周知,在java中有两种方法(或者以上)解决并发的临界资源问题 一种是通过加锁来实现的,即synchronized. 还有一种是ThreadLocal的方法来解决的 但是本人还是对后者有不理解的地方(或者说是什么情况下该用synchronized,什么情况下该用),特此来请教各路大神 同步采用了"以时间换空间的思想",而ThreadLocal采用"以空间换取时间的"思想 public class Chopsticks { String name; pr

深入理解Python中的ThreadLocal变量(中)

在 深入理解Python中的ThreadLocal变量(上)中我们看到 ThreadLocal 的引入,使得可以很方便地在多线程环境中使用局部变量.如此美妙的功能到底是怎样实现的?如果你对它的实现原理没有好奇心或一探究竟的冲动,那么接下来的内容估计会让你后悔自己的浅尝辄止了. 简单来说,Python 中 ThreadLocal 就是通过下图中的方法,将全局变量伪装成线程局部变量,相信读完本篇文章你会理解图中内容的.(对这张图不眼熟的话,可以回顾下上篇)). 在哪里找到源码? 好了,终于要来分析

Java多线程原理及ThreadLocal多线程实例详解

一.线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是程序的一个动态执行过程,是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 Windows系统中,一个运行的exe就是一个进程.线程是指进程中的一个执行流程,一个进程中可以运行多个线程.比如java.exe进程中可以运行很多线程.线程总是属于某个进程,进程中的多个线程共享进程的内存."同时"执行是人的感觉,在线程之间实际上轮换执行. 二.Java

ThreadLocal是否会引发内存泄露的分析 good

这篇文章,主要解决一下疑惑: 1. ThreadLocal.ThreadLocalMap中提到的弱引用,弱引用究竟会不会被回收? 2. 弱引用什么情况下回收? 3. JAVA的ThreadLocal和在什么情况下会内存泄露?   带着这些疑问,自己模拟了一下ThreadLocal.ThreadLocalMap的结构,先展示下自己涉及的结构: 自己实现一个simple的ThreadLocalMap,里面用一个entry用来存放由自己模拟的ThreadLocal调用set方法set进去的值. 并且和

Android 中 ThreadLocal使用示例

Android 中 ThreadLocal使用示例 概要: Demo描述: ThreadLocal使用示例. 关于ThreadLocal的官方文档描述 Implements a thread-local storage, that is, a variable for which each thread has its own value. All threads share the same ThreadLocal object, but each sees a different value

dreaweaver-关于网页边框使用的问题,新手有疑问

问题描述 关于网页边框使用的问题,新手有疑问 右下边框mp3,视频,图片--这个内嵌表格为什么不是在左上角开始,而是跑中间去了-求解 解决方案 td默认就是水平居中的,你要居上给td添加valign="top" <td width="760" valign="top"> 解决方案二: 新手使用python常见问题 解决方案三: 给table或者td写样式啊,实在不行就打开开发者工具看看居中的那个块元素在哪个位置.然后根据实际情况去加样

java中++a和a++ 在数组实现栈中的小疑问

问题描述 java中++a和a++ 在数组实现栈中的小疑问 package 数组实现栈; public class StackArray implements Stack { public static final int num = 1024;//数组默认容量 public int capacity;//数组实际容量 public Object s[];//对象数组 public int top = -1;//栈顶元素位置 //构建默认容量栈对象 public StackArray() { t

软件测试-linux代码覆盖率测试工具gcov的一些疑问?

问题描述 linux代码覆盖率测试工具gcov的一些疑问? 鄙人是做软件测试的,最近在使用gcov来检查代码覆盖率,我已经成功生成了一份关于touchscreen测试代码的gcov文件,但是领导说这不是他想要的...所以我想请教一下大家:1. 如果我想测试平台上的touchscreen模块,那么目的肯定是这样:首先我要看下我写的测试code是否存在多余的根本跑不到的代码,如果有,那我肯定要优化我的测试代码:其次,我肯定也要看我写的代码在linux kernel里面的覆盖情况,如果我写的测试代码在