概述
1个对象被多个线程同时引用且操作(比如作为线程的成员变量),会引发线程安全的问题。但是可以通过给该对象设置ThreadLocal属性,来实现一个对象在不同线程里面,同时操作ThreadLocal属性时,相互隔离的效果。
使用示范
为了解决公用变量不安全的情况,可以通过ThreadLocal来定义某些变量为线程独有的,从而实现线程隔离
例如下面的,对线程私有变量 number进行threadlocal处理,对于公用变量 sharedNumber不做处理,实现线程共享传递参数
public class SeqCount {
private static ThreadLocal<Integer> number = new ThreadLocal<Integer>(){
public Integer initialValue() {
return 0;
}
};
int sharedNumber=0;
public int nextSeq(){
number.set(number.get() + 1);
return number.get();
}
public static void main(String[] args){
SeqCount seqCount = new SeqCount();
for(int i=0;i<4;i++){
new SeqThread(seqCount).start();
}
}
private static class SeqThread extends Thread{
private SeqCount seqCount;
SeqThread(SeqCount seqCount){
this.seqCount = seqCount;
}
public void run() {
for(int i = 0 ; i < 3 ; i++){
System.out.println(Thread.currentThread().getName() + " seqCount :" + seqCount.nextSeq());
seqCount.sharedNumber++;
System.out.println(Thread.currentThread().getName() + " shareNumber :" + seqCount.sharedNumber);
}
}
}
}
ThreadLocal实现线程隔离原理:
每个Thread独立拥有一个ThreadLocalMap,实现线程之间变量的隔壁,然后set、get都是对这个ThreadLocalMap进行操作,其中的key就是申明的ThreadLocal,线性探测法实现的HashMap的数据结构
Thread :每个Thread只有一个独立绑定的ThreadLocalMap,线程独享
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
ThreadLocalMap:每个ThreadLocalMap拥有一个线性探测的HashMap结构,每个Entry的key就是一个ThreadLocal
private Entry getEntry(ThreadLocal key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
ThreadLocal : 每个Thread可以定义多个ThreadLocal
private static ThreadLocal<Integer> number = new ThreadLocal<Integer>(){
public Integer initialValue() {
return 0;
}
};
private static ThreadLocal<Integer> number2 = new ThreadLocal<Integer>(){
public Integer initialValue() {
return 1;
}
};
网友评论