在java中,变量的共享可以使用Public static 变量的形式进行声明,所有的线程都可以使用被Public static 声明的变量。但如果我们想要每一个线程都有自己的共享变量?(换个角度讲,每一个线程中的变量名相同而引用的值不一样)。JDK提供了ThreadLocal用于解决这样的问题。
举个例子:
public class ThreadLocalDemo {
public ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public void setThreadLocal(Integer number){
threadLocal.set(number);
}
public void getThreadLocal(){
System.out.println(Thread.currentThread().getName()+":"+threadLocal.get());
}
public static void main(String[] args){
ThreadLocalDemo demo = new ThreadLocalDemo();
new Thread(new Runnable() {
@Override
public void run() {
demo.setThreadLocal(10);
demo.getThreadLocal();
}
},"th1").start();
new Thread(new Runnable() {
@Override
public void run() {
demo.setThreadLocal(5);
demo.getThreadLocal();
}
},"th2").start();
}
}
运行结果:
可见,虽然多个线程对threadLocal这个变量进行访问,但由于threadLocal被ThreadLocal所修饰,不同线程访问的是本身线程设置的值。实际上ThreadLocal为每一个使用该变量的线程创建了一个副本,线程访问的是自己的副本而不会受其他线程副本的影响。实现的思路在threadLocal中有一个static的Map,其中key为线程,value为对应的副本。
ThreadLocal与Synchronized的比较:
- 在同步机制中,Synchronized采用了锁机制保证了同一时刻只有一个线程访问变量。ThreadLocal没有采用锁机制,而是以空间换时间的方式,为每个线程创建独立的副本来保证线程的安全。
- 采用锁机制,需要慎密的考虑需要锁定什么对象,什么时候进行锁定以及什么时候进行锁的释放,在程序设计和编写上变得偏复杂。