网上关于Threadloal的文章很多,有时看多了我自己也搞不清这东西到底干嘛用的了,而且有些例子举得也是有问题的,下面我谈下自己的理解。
先摘抄一个别人的:
ThreadLocal:允许我们创建只能被同一个线程读写的变量,例如Web应用中将变量从前端到后台,并且需要在这次请求的线程中始终可以随时获取到。
我的理解:
其实说得也比较好懂,我这只有一个变量,我也不想再创建了,但是偏偏有三个线程需要使用这个变量,如果单纯这么使用,那肯定是会出现线程安全问题;不能理解的话就再打个比喻,例如苍老师在拍片,此时有三个猛男都要跟苍老师啪啪啪,这肯定不行的嘛,要么你一个一个来还是可以的。
但是三个猛男偏偏都想要跟苍老师玩,而且都不想排队,这就麻烦了,此时。。。我们的导演ThreadLocal 来了,导演并不是空手而来,而是背着好几个以苍老师为模板的充气娃娃,然后对着那三个猛男说道,你们几个玩这个娃娃吧,让苍老师先休息一下。
三猛男此时都得到一个娃娃,然后就乐此不疲的去拍摄了。。。虽然没真人那么爽,但至少不用排队或者争着来了,也不会弄错了,只与自己的娃娃玩嘛,其他人的娃娃让他自己玩去!
下面我会用代码来表示一下:
1. 没使用ThreadLocal 的情况下:
import java.util.Random;
/**
* Created by ThinkPad on 2017/3/10.
*/
public class NoThreadLocalTestCount {
static int count=1;
public static void main(String[] args) {
for(int i=0;i<3;i++){
new Thread(new Runnable() {
public void run() {
Random random = new Random();
count= random.nextInt(1000);
System.out.println(Thread.currentThread()+":"+count);
try {
Thread.sleep(1000);
}catch (Exception e){
}
Aclass.test();
}
}).start();
}
}
static class Aclass{
public static void test(){
System.out.println("进入a模块:"+Thread.currentThread()+":"+count);
}
}
}
结果:
Thread[Thread-2,5,main]:398
Thread[Thread-1,5,main]:368
Thread[Thread-0,5,main]:348
进入a模块:Thread[Thread-2,5,main]:348
进入a模块:Thread[Thread-1,5,main]:348
进入a模块:Thread[Thread-0,5,main]:348
其实我希望的是输出结果是:
thread-1 368
进入a模块:Thread[Thread-1,5,main]:368
但是结果都给我输出348,与预期结果不符合呀,因为多线程去操作时,变量count被改变了,另一线程拿到是别的线程改变后的结果。
为了杜绝这个问题,我们使用ThreadLocal来进行测试:
import java.util.Random;
/**
* Created by ThinkPad on 2017/3/10.
*/
public class ThreadLocalTest {
static ThreadLocal <Integer> localCount=new ThreadLocal<Integer>();
//线程独享该变量的副本,而并不影响其他线程获取该数据,即2个线程对该变量的操作互不影响,
//适用于数据库连接管理,session管理等等,
public static void main(String[] args) {
for(int i=0;i<3;i++){
new Thread(new Runnable() {
public void run() {
Random random = new Random();
int count= random.nextInt(1000);
localCount.set(count);
System.out.println(Thread.currentThread()+":"+count);
try {
Thread.sleep(1000);
}catch (Exception e){
}
Aclass.test();
}
}).start();
}
}
static class Aclass{
public static void test(){
System.out.println("进入a模块:"+Thread.currentThread()+":"+localCount.get());
}
}
结果:
Thread[Thread-0,5,main]:114
Thread[Thread-2,5,main]:75
Thread[Thread-1,5,main]:693
进入a模块:Thread[Thread-0,5,main]:114
进入a模块:Thread[Thread-1,5,main]:693
进入a模块:Thread[Thread-2,5,main]:75
哟...结果还是可以的嘛!对应的线程,哪怕中间有别的线程在操作,也不影响本线程的数据,我的依然是我的,你的还是你的,互不干扰挺好的。那个...听说strus2用这个保证接收的参数变量每个线程是隔离的,以前学习时也不太懂...现在想想确实也这么回事,要是不这样的话,写在action里的成员变量就乱咯,除非使用多例模式可避免。
嗯,今天先到此了,下次再见,拜拜!