大神们,请问tread和threadlocal作用的作用和区别是什么

关于作者: paddx
查看paddx的更多文章 >>
转载请注明:
高效,专业,符合SEO下午没事的时候,写了一个关于ThreadLocal的例子。
以前对这个一直没有太在意,看书的时候基本上没有用过。以前写代码的时候,外加做web开发的,基本上用到Thread的东西很少。当时以为这个ThreadLocal以就Thread里面的一个东西。&就没太在意。下午没事,把这个想起来了,写了一个简单的例子。费话少说:
package&com.websidesoft.public&class&User&...{&&&&private&String&&&&&private&String&&&&&private&int&&&&&&&&&public&int&getAge()&...{&&&&&&&&return&&&&&}&&&&public&void&setAge(int&age)&...{&&&&&&&&this.age&=&&&&&}&&&&public&String&getPassword()&...{&&&&&&&&return&&&&&}&&&&public&void&setPassword(String&password)&...{&&&&&&&&this.password&=&&&&&}&&&&public&String&getUsername()&...{&&&&&&&&return&&&&&}&&&&public&void&setUsername(String&username)&...{&&&&&&&&this.username&=&&&&&}&&&&@Override&&&&public&String&toString()&...{&&&&&&&&return&getClass().getName()&&&&&&&&&&&&+&&:&username&=&&&+&username&&&&&&&&&&&&+&&,&password&=&&&+&password&&&&&&&&&&&&+&&,&age&=&&&+&&&&&}}
上面是用到一个普通的Bean。下面是实现了ThreadLocal的一个类。不去解释里面的方面的含义了。不明白自己google一下,网上多的是。或者看看API.
package&com.websidesoft.public&class&ThreadLocalSample&extends&ThreadLocal&...{&&&&private&static&ThreadLocalSample&local&=&new&ThreadLocalSample();&&&&private&User&&&&&&&&&&&&&protected&Object&initialValue()&...{&&&&&&&&user&=&new&User();&&&&&&&&user.setUsername(&Gavin&);&&&&&&&&user.setPassword(&密码&);&&&&&&&&user.setAge(<span style="COLOR: #);&&&&&&&&return&&&&&}&&&&&&&&public&User&getUser()&...{&&&&&&&&return&(User)local.get();&&&&}}
上面的类就实现在了一个简单的ThreadLocal。ThreadLocal对每一个线程保正会取到同一个对象。比如在我们写数据库连接的时候,可以多个DAO都会调用同一个Connection,怎么保存呢?这个正好是最佳使用时机。
下面写了一个简单的测试类,测试我们的结果是否正确。
package&com.websidesoft.import&java.util.ArrayLimport&java.util.Lpublic&class&TestThreadLocal&extends&Thread&...{&&&&public&static&List&User&&list&=&new&ArrayList();&&&&&&&&public&void&run()&...{&&&&&&&&for&(int&i&=&<span style="COLOR: #;&i&&&<span style="COLOR: #;&i++)&...{&&&&&&&&&&&&ThreadLocalSample&tt&=&new&ThreadLocalSample();&&&&&&&&&&&&list.add(tt.getUser());&&&&&&&&}&&&&}&&&&&&&&public&static&void&main(String[]&args)&...{&&&&&&&&for&(int&i&=&<span style="COLOR: #;&i&&&<span style="COLOR: #;&i++)&...{&&&&&&&&&&&&TestThreadLocal&ta&=&new&TestThreadLocal();&&&&&&&&&&&&ta.start();&&&&&&&&}&&&&&&&&&&&&&&&&try&...{&&&&&&&&&&&&sleep(<span style="COLOR: #00);&&&&&&&&}&catch&(InterruptedException&e)&...{&&&&&&&&&&&&e.printStackTrace();&&&&&&&&}&&&&&&&&&&&&&&&&Object&o1&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&Object&o2&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&Object&o3&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&Object&o4&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&Object&o5&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&Object&o6&=&TestThreadLocal.list.get(<span style="COLOR: #);&&&&&&&&&&&&&&&&System.out.println(o1.equals(o2));&&//true&&&&&&&&System.out.println(o3.equals(o4));&&&&//true&&&&&&&&System.out.println(o1.equals(o4));&&&&//false&&&&&&&&System.out.println(o5.equals(o6));&&&&//true&&&&&&&&System.out.println(o1.equals(o5));&&&&//false&&&&&&&&System.out.println(o2.equals(o6));&&&&//false&&&&}}
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1828次
排名:千里之外Android基础、文档、工具、控件(25)
线程同步机制:
目的:解决多线程中相同变量的访问冲突问题。
在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的。
使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题。
经典案例:多生产者和多消费者。
ThreadLocal:
ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。
ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。(ThreadLocalVariables可能更好理解点)
个人理解:每个线程中各自用独立的对象。可以很方便的获取在本线程中存储的对象,拍案惊奇!!!应该要有一个ThreadLocalMananger,保持ThreadLocal为单例,在Handler机制里面Looper中为static final,被所有线程中Looper共享。
当某些数据是以线程为作用域并且不同线程具有不同的数据副本的时候,可以考虑采用ThreadLocal。
android中源码ThreadLocal中。
Thread中持有TreadLocal.Values,
每一个线程就有一个Values,所以每一个线程都有Object[]数组 table。通过数组角标来获取该线程局部变量。
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
values.put(this, value);
Values values(Thread current) {
return current.localV
public T get() {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.
int index = hash & values.
if (this.reference == table[index]) {
return (T) table[index + 1];
values = initializeValues(currentThread);
return (T) values.getAfterMiss(this);
Values initializeValues(Thread current) {
return current.localValues = new Values();
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:112014次
积分:2373
积分:2373
排名:第15454名
原创:128篇
评论:44条
阅读:29043
阅读:3802
(1)(1)(5)(2)(25)(1)(5)(4)(1)(1)(20)(5)(7)(17)(18)(2)(2)(7)(5)(2)posts - 262,&
comments - 221,&
trackbacks - 0
关于ThreadLocal的用法,之前一直不太清楚,直到最近看了网上一篇文章,再结合SUN的API,才对这个类有了一定的了解。
ThreadLocal的核心思想很简单:为每个独立的线程提供一个变量的副本。
我们知道在多线程的情况下,几个线程同时访问同一变量的情况很常见,Java提供的synchronized关键字使用了&#8220;同步锁&#8221;的机制来阻止线程的竞争访问,即&#8220;以时间换空间&#8221;。
ThreadLocal则使用了&#8220;拷贝副本&#8221;的方式,人人有份,你用你的,我用我的,大家互不影响,是&#8220;以空间换时间&#8221;。每个线程修改变量时,实际上修改的是变量的副本,不怕影响到其它线程。
ThreadLocal的一个最常见应用是为每个线程分配一个唯一的ID,例如线程ID,事务ID,一般保存在ThreadLocal中的变量都是很少需要修改的。
为了加深对ThreadLocal的理解,下面我使用一个例子来演示ThreadLocal如何隔离线程间的变量访问和修改:
【1】SerialNum类
package&example.thread.threadL
public&class&SerialNum&{
&&&&private&static&int&nextSerialNum&=&<span style="color: #;
&&&&&#64;SuppressWarnings("unchecked")
&&&&private&static&ThreadLocal&serialNum&=&new&ThreadLocal()&{
&&&&&&&&protected&synchronized&Object&initialValue()&{
&&&&&&&&&&&&return&new&Integer(nextSerialNum++);&&&&&&
&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&public&static&int&get()&{
&&&&&&&&return&((Integer)&(serialNum.get())).intValue();
&&&&&#64;SuppressWarnings("unchecked")
&&&&public&static&void&set(Integer&newSerial){
&&&&&&&&serialNum.set(newSerial);
【2】GetSerialNumThread
package&example.thread.threadL
public&class&GetSerialNumThread&implements&Runnable&{
&&&&public&static&void&main(String&args[])&{
&&&&&&&&GetSerialNumThread&serialNumGetter&=&new&GetSerialNumThread();
&&&&&&&&Thread&t1&=&new&Thread(serialNumGetter,&"Thread&A");
&&&&&&&&Thread&t2&=&new&Thread(serialNumGetter,&"Thread&B");
&&&&&&&&t1.start();
&&&&&&&&try&{
&&&&&&&&&&&&t1.join();
&&&&&&&&}&catch&(InterruptedException&e)&{
&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&}&&&&
&&&&&&&&t2.start();&&&&&&&&&&&&
&&&&public&void&run()&{
&&&&&&&&int&mySerialNum&=&getSerialNum();
&&&&&&&&System.out.println("线程&"&+&Thread.currentThread().getName()
&&&&&&&&&&&&&&&&+&"&获取到的序列号是"&+&mySerialNum);
&&&&&&&&System.out.println("线程&"&+&Thread.currentThread().getName()
&&&&&&&&&&&&&&&&+&"&修改了序列号为"&+&(mySerialNum&*&<span style="color: #));
&&&&&&&&setSerialNum(mySerialNum&*&<span style="color: #);
&&&&&&&&System.out.println("线程&"&+&Thread.currentThread().getName()
&&&&&&&&&&&&&&&&+&"&再次获得的序列号是"&+&getSerialNum());
&&&&private&int&getSerialNum()&{
&&&&&&&&return&SerialNum.get();
&&&&private&void&setSerialNum(int&newSerialNum)&{
&&&&&&&&SerialNum.set(new&Integer(newSerialNum));
运行的结果如下:
线程&Thread&A&获取到的序列号是1
线程&Thread&A&修改了序列号为3
线程&Thread&A&再次获得的序列号是3
线程&Thread&B&获取到的序列号是2
线程&Thread&B&修改了序列号为6
线程&Thread&B&再次获得的序列号是6
可见第一个线程在调用SerialNum.set(int)方法修改static变量时,其实修改的是它自己的副本,而不是修改本地变量,第二个线程在初始化的时候拿到的序列号是2而不是7。
为什么会这样呢?明明serialNum是静态变量啊?其实我们只需要看看ThreadLocal的内部构造就知道了:
A. ThreadLocal的get()方法:
&&&&&*&Returns&the&value&in&the&current&thread's&copy&of&this&thread-local
&&&&&*&variable.&&Creates&and&initializes&the&copy&if&this&is&the&first&time
&&&&&*&the&thread&has&called&this&method.
&&&&&*&&#64;return&the&current&thread's&value&of&this&thread-local
&&&&public&T&get()&{
&&&&&&&&Thread&t&=&Thread.currentThread();
&&&&&&&&ThreadLocalMap&map&=&getMap(t);
&&&&&&&&if&(map&!=&null)
&&&&&&&&&&&&return&(T)map.get(this);
&&&&&&&&//&Maps&are&constructed&lazily.&&if&the&map&for&this&thread
&&&&&&&&//&doesn't&exist,&create&it,&with&this&ThreadLocal&and&its
&&&&&&&&//&initial&value&as&its&only&entry.
&&&&&&&&T&value&=&initialValue();
&&&&&&&&createMap(t,&value);
&&&&&&&&return&
B. ThreadLocal的set()方法:
&&&&&*&Sets&the&current&thread's&copy&of&this&thread-local&variable
&&&&&*&to&the&specified&value.&&Many&applications&will&have&no&need&for
&&&&&*&this&functionality,&relying&solely&on&the&{&#64;link&#initialValue}
&&&&&*&method&to&set&the&values&of&thread-locals.
&&&&&*&&#64;param&value&the&value&to&be&stored&in&the&current&threads'&copy&of
&&&&&*&&&&&&&&this&thread-local.
&&&&public&void&set(T&value)&{
&&&&&&&&Thread&t&=&Thread.currentThread();
&&&&&&&&ThreadLocalMap&map&=&getMap(t);
&&&&&&&&if&(map&!=&null)
&&&&&&&&&&&&map.set(this,&value);
&&&&&&&&else
&&&&&&&&&&&&createMap(t,&value);
可以看到ThreadLocal在内部维护了一个Map,将变量的值和线程绑定起来,get/set方法都是对该线程对应的value进行操作,所以不会影响到其它线程。
-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
阅读(4457)
&re: 【原】Java 多线程 之 ThreadLocal
在MyEclipse中开发基于hibernate的程序时,自动生成的Session工厂就用了ThreadLocal,以保证每一个线程只有一个Session。 实际上,ThreadLocal的基本原理就是利用线程的id作为Map的key,将一个对象作为Map的value, 以保证一个线程只有一个key-value对。由于每一个线程有一个独立的对象,而且每个线程的对象必须独立,也就是说不能有其他的线程访问当前线程的对象,这样对于每个线程来说,是顺序执行的,也就不可能发生象脏数据这样的事情了。&&&&&&
31167891011121314151617181920212223242526272829301234567891011
留言簿(18)
BlogJava热点博客
阅读排行榜
评论排行榜

我要回帖

更多关于 java threadlocal作用 的文章

 

随机推荐