从字面上看它好像是一个本地线程,但其实它不是一个线层,而是当前线层Thread的局部变量。
使用场景:在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻只有一个线程对共享变量进行操作。这种情况下可以将类变量放到ThreadLocal类型的对象中,使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。
ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:
void get()
void set(Object value)
public void remove()
protected Object initialValue()
它只有这四个方法
get(),set(),无非就是给当前线程取得当前线程的局部变量和设置当前线程的局部变量, remove()是清楚这个线程的局部变量,其实可以不用清楚,当该线程的生命周期结束时,此变量的内存会被自动回收,加了是便于快速回收节约内存。
来看下ThreadLocal源码
public class ThreadLocal<T>
private Map values = Collections.synchronizedMap(new HashMap());
public T get()
{
Thread curThread = Thread.currentThread();
T o = values.get(curThread);
if (o == null && !values.containsKey(curThread))
{
o = initialValue();
values.put(curThread, o);
}
values.put(Thread.currentThread(), newValue);
return o ;
}
protected Object initialValue()
{
return null;
}
public set(T t){
Thread curThread = Thread.currentThread();
T o = values.get(curThread);
if (o == null && !values.containsKey(curThread))
{
o = initialValue();
values.put(curThread, o);
}
values.put(curThread , t);
}
public void remove(){
values.remove(Thread.currentThread());
}
}
原理很简单,就放了一个map用来放置当前线程的全局变量,set,get无非就是从map里面去取,或者放而已。
它防止多线程访问同一个变量时出现线程不安全的问题,但是它和
synchronized有很大区别
在
synchronized中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用
synchronized要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放
对象锁等繁杂的问题,程序设计和编写难度相对较大。
而ThreadLocal则从另一个角度来解决多线程的并发访问。在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
jdbc数据库连接connection的
ThreadLocal实例
public
class
ConnectionUtil {
private
static
ThreadLocal<Connection> tl =
new
ThreadLocal<Connection>();
private
static
Connection initConn =
null
;
static
{
try
{
initConn = DriverManager.getConnection(
"url, name and password"
);
}
catch
(SQLException e) {
e.printStackTrace();
}
}
public
Connection getConn() {
Connection c = tl.get();
tl.set(initConn);
return
c;
}
}