ThreadLocal的核心思想很简单:为每个独立的线程提供一个变量的副本。
Java提供的synchronized关键字使用了“同步锁”的机制来阻止线程的竞争访问,即“以时间换空间”。: " 10pt; FONT-SIZE:> ThreadLocal则使用了“拷贝副本”的方式,人人有份,你用你的,我用我的,大家互不影响,是“以空间换时间”。每个线程修改变量时,实际上修改的是变量的副本,不怕影响到其它线程。
为了加深对ThreadLocal的理解,下面我使用一个例子来演示ThreadLocal如何隔离线程间的变量访问和修改:
【1】SerialNum类
packageexample.thread.threadLocal;
publicclassSerialNum{
privatestaticintnextSerialNum=1;
@SuppressWarnings("unchecked")
privatestaticThreadLocalserialNum=newThreadLocal(){
protectedsynchronizedObjectinitialValue(){
returnnewInteger(nextSerialNum++);
}
};
publicstaticintget(){
return((Integer)(serialNum.get())).intValue();
}
@SuppressWarnings("unchecked")
publicstaticvoidset(IntegernewSerial){
serialNum.set(newSerial);
}
}
【2】GetSerialNumThread
packageexample.thread.threadLocal;
publicclassGetSerialNumThreadimplementsRunnable{
publicstaticvoidmain(Stringargs[]){
GetSerialNumThreadserialNumGetter=newGetSerialNumThread();
Threadt1=newThread(serialNumGetter,"ThreadA");
Threadt2=newThread(serialNumGetter,"ThreadB");
t1.start();
try{
t1.join();
}catch(InterruptedExceptione){
e.printStackTrace();
} t2.start();
}
publicvoidrun(){
intmySerialNum=getSerialNum();
System.out.println("线程"+Thread.currentThread().getName()
+"获取到的序列号是"+mySerialNum);
System.out.println("线程"+Thread.currentThread().getName()
+"修改了序列号为"+(mySerialNum*3));
setSerialNum(mySerialNum*3);
System.out.println("线程"+Thread.currentThread().getName()
+"再次获得的序列号是"+getSerialNum());
}
privateintgetSerialNum(){
returnSerialNum.get();
}
privatevoidsetSerialNum(intnewSerialNum){
SerialNum.set(newInteger(newSerialNum));
}
}
责任编辑:小草