如果你有这样的需求,在不同的线程中对某个对象的修改不会影响到其它线程中该对象的状态,那么使用ThreadLocal将是非常不错的解决方案,事实上,这种需求是很常见的;
我们来演示一下ThreadLocal的工作机制:
//测试线程本地存储,证明对象复制与多个线程对ThreadLocal变量的修改互不影响
private static void testLocalThread() throws InterruptedException {
class TempObj{}
class Local{
//用来证明本地线程会为每个线程复制一份单独的对象!
private ThreadLocal<TempObj> objValue = new ThreadLocal<TempObj>(){
@Override
protected TempObj initialValue() {//初始化值
return new TempObj();
}
};
//用来证明多个线程对ThreadLocal变量的修改互不影响!
private ThreadLocal<Integer> value = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return new Random().nextInt(1000);
}
};
//随机填充value的值
private void fill(){
value.set( new Random().nextInt(1000));
}
@Override
public String toString() {
return "当前线程:"+Thread.currentThread()+"当前值:"+this.value.get()+","
+"tempObj:"+this.objValue.get();
}
}
ExecutorService exec = Executors.newCachedThreadPool();
final Local local = new Local();
System.out.println(local);
System.out.println("#########开启多个线程改变值########");
for (int i = 0; i < 10; i++) {
exec.execute(new Runnable() {
@Override
public void run() {
local.fill();
System.out.println(local);
}
});
}
TimeUnit.MILLISECONDS.sleep(100);
System.out.println("#########开启多个线程改变值完毕########");
System.out.println(local);
}
输出*****************************************************************************
当前线程:Thread[main,5,main]当前值:7,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@13d5e499
#########开启多个线程改变值########
当前线程:Thread[pool-1-thread-2,5,main]当前值:406,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@2396649c
当前线程:Thread[pool-1-thread-1,5,main]当前值:63,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@66a75004
当前线程:Thread[pool-1-thread-1,5,main]当前值:379,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@66a75004
当前线程:Thread[pool-1-thread-3,5,main]当前值:363,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@4b90690e
当前线程:Thread[pool-1-thread-2,5,main]当前值:680,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@2396649c
当前线程:Thread[pool-1-thread-1,5,main]当前值:37,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@66a75004
当前线程:Thread[pool-1-thread-5,5,main]当前值:117,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@165e6c89
当前线程:Thread[pool-1-thread-3,5,main]当前值:601,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@4b90690e
当前线程:Thread[pool-1-thread-6,5,main]当前值:503,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@1127a1d8
当前线程:Thread[pool-1-thread-4,5,main]当前值:603,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@40f274b4
#########开启多个线程改变值完毕########
当前线程:Thread[main,5,main]当前值:7,tempObj:com.fyrj.compoment.demo.thread2.ShareResource$1TempObj@13d5e499
**********************************************************************************
我们可以看到。多个线程都会去改变value的值,而最后那一行输出证明了main线程的值从未变过,还是7;
而对tempObj对象地址打印也证明了,每开启一个新的线程,ThreadLocal里面装载的都不会是同一个对象,而是它的复制品!所以当然可以放心的修改对象的状态!