转自:http://hi.baidu.com/%BB%98%D7%D3%D6%E0/blog/item/b5eaa4340d5adf83a71e1219.html
早在Java
1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择。使用
这个工具类可以很简洁地编写出优美的多线程程序,虽然ThreadLocal非常有用,但是似乎现在了解它、使用它的朋友还不多。
ThreadLocal是什么
ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread
local
variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,
就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每
一个线程都完全拥有该变量。线程局部变量并不是Java的新发明,在其它的一些语言编译器实现(如IBM XL
FORTRAN)中,它在语言的层次提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支
持,所以,在Java中编写线程局部变量的代码相对比较笨拙,这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。
ThreadLocal的设计
首先看看ThreadLocal的接口:
Object get() ; // 返回当前线程的线程局部变量副本 protected Object initialValue(); //
返回该线程局部变量的当前线程的初始值void set(Object value); // 设置当前线程的线程局部变量副本的值
ThreadLocal有3个方法,其中值得注意的是initialValue(),该方法是一个protected的方法,显然是为了子类重写而特
意实现的。该方法返回当前线程在该线程局部变量的初始值,这个方法是一个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执
行,并且仅执行1次。ThreadLocal中的确实实现直接返回一个null:
protected Object initialValue() { return null; }
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:
1
public
class
ThreadLocal
2
{
3
private
Map
values
=
Collections
.
synchronizedMap
(
new
HashMap
());
4
public
Object
get
()
5
{
6
Thread
curThread
=
Thread
.
currentThread
();
7
Object
o
=
values
.
get
(
curThread
);
8
if
(
o
==
null
&&
!
values
.
containsKey
(
curThread
))
9
{
10
o
=
initialValue
();
11
values
.
put
(
curThread
,
o
);
12
}
13
return
o
;
14
}
15
16
public
void
set
(
Object
newValue
)
17
{
18
values
.
put
(
Thread
.
currentThread
(),
newValue
);
19
}
20
21
public
Object
initialValue
()
22
{
23
return
null
;
24
}
25
}
当然,这并不是一个工业强度的实现,但JDK中的ThreadLocal的实现总体思路也类似于此。
ThreadLocal的使用
如果希望线程局部变量初始化其它值,那么需要自己实现ThreadLocal的子类并重写该方法,通常使用一个内部匿名类对ThreadLocal进行子类化,比如下面的例子,SerialNum类为每一个类分配一个序号:
1
public
class
SerialNum
2
{
3
// The next serial number to be assigned
4
5
private
static
int
nextSerialNum
=
0
;
6
private
static
ThreadLocal
serialNum
=
new
ThreadLocal
()
7
{
8
protected
synchronized
Object
initialValue
()
9
{
10
return
new
Integer
(
nextSerialNum
++);
11
}
12
};
13
14
public
static
int
get
()
15
{
16
return
((
Integer
)
(
serialNum
.
get
())).
intValue
();
17
}
18
}
SerialNum类的使用将非常地简单,因为get()方法是static的,所以在需要获取当前线程的序号时,简单地调用:
int serial = SerialNum.get();
即可。
在线程是活动的并且ThreadLocal对象是可访问的时,该线程就持有一个到该线程局部变量副本的隐含引用,当该线程运行结束后,该线程拥有的所以线程局部变量的副本都将失效,并等待垃圾收集器收集。
ThreadLocal与其它同步机制的比较
ThreadLocal和其它同步机制相比有什么优势呢?ThreadLocal和其它所有的同步机制都是为了解决多线程中的对同一变量的访问冲突,
在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候对
变量进行读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的。ThreadLocal就从另一
个角度来解决多线程的并发访问,ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每一个线程都拥有自
己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的整个变量封装
进ThreadLocal,或者把该对象的特定于线程的状态封装进ThreadLocal。
由于ThreadLocal中可以持有任何类型的对象,所以使用ThreadLocal
get当前线程的值是需要进行强制类型转换。但随着新的Java版本(1.5)将模版的引入,新的支持模版参数的
ThreadLocal<T>类将从中受益。也可以减少强制类型转换,并将一些错误检查提前到了编译期,将一定程度地简化
ThreadLocal的使用。
总结
当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行
通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步
了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化
你的程序,使程序更加易读、简洁。
分享到:
相关推荐
深入研究java.lang.ThreadLocal类。ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是 threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。
入研究java.lang.ThreadLocal类.docx
简单分析Java线程编程中ThreadLocal类的使用共4页.pdf.zip
Java中ThreadLocal工具类(解决多线程程序中并发问题的一种新思路,主要为参数的拷贝问题),感兴趣的话可以查看博文,博文地址:http://blog.csdn.net/otengyue/article/details/38459327
NULL 博文链接:https://justsee.iteye.com/blog/791919
主要介绍了Java ThreadLocal类应用,结合具体案例形式分析了java ThreadLocal类的功能、原理、用法及相关操作注意事项,需要的朋友可以参考下
什么是ThreadLocal?顾名思义它是local variable(线程局部变量)。它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
主要介绍了实例讲解Java并发编程之ThreadLocal类,本文给出了模拟ThreadLocal、实用ThreadLocal等代码实例,需要的朋友可以参考下
主要介绍了快速了解Java中ThreadLocal类,介绍了ThreadLocal 是什么,ThreadLocal的作用,ThreadLocal 原理等相关内容,具有一定参考价值,需要的朋友可以了解下。
DbUTils中用ThreadLocal类
主要介绍了Java多线程编程中ThreadLocal类的用法及深入,尝试了自己实现一个ThreadLocal类以及对相关的线程安全问题进行讨论,需要的朋友可以参考下
ThreadLocalMap是ThreadLocal类中的内部类,实例却被Thread类持有,相当于每个线程持有一个map
主要介绍了Java线程编程中ThreadLocal类的使用,包括使用其对共享变量的操作的分析,需要的朋友可以参考下
资源名称:Java多线程与并发库高级应用视频教程22集资源目录:【】01传统线程技术回顾【】02传统...06ThreadLocal类及应用技巧【】06ThreadLocal类及应 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
JDBC事务的封装和Threadlocal实例,参考博客:http://blog.csdn.net/daijin888888/article/details/50988053
利用过滤器去获取request和response,进行将其设置到ThreadLocal从而保证我的请求的安装线,这样就能在java普通类中获取request和response
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
remove是java.lang.ThreadLocal类的方法,但是jdk1.4中,却没有这个方法的实现,jdk1.5中有这个方法,因此是没问题的; 本jar包经过改造,适用于JDK1.4,需要第三方JAR包的支持(commons-beanutils-1.8.2.jar,commons-...