ThreadLocal(线程变量副本)
Synchronized实现内存共享,ThreadLocal为每个线程维护一个本地变量。
采用空间换时间,它用于线程间的数据隔离,为每一个使用该变量的线程提供一个副本,每个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突。
ThreadLocal类中维护一个Map,可以点开看源码,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值为对应线程的变量副本。
ThreadLocal在Spring中发挥着巨大的作用,在管理Request作用域中的Bean、事务管理、任务调度、AOP等模块都出现了它的身影。
Spring中绝大部分Bean都可以声明成Singleton作用域,采用ThreadLocal进行封装,因此有状态的Bean就能够以singleton的方式在多线程中正常工作了。
下边是我写的一个普通int类型跟ThreadLocal变量的对比,证明threadlocal 跟线程绑定的
/**
* @author: zhengyanchun
* @since: 2020.12.17 16:58
**/
public class TestTheadLocal {
public static void main(String[] args) throws InterruptedException {
PartnerThreadLocal.setPartnerId(1L);
PartnerThreadLocal.setI(10);
new AutoClipTimer().schedule(() -> {
Long partnerId = PartnerThreadLocal.getPartnerId();
System.out.println(partnerId);
int i = PartnerThreadLocal.getI();
System.out.println(i);
}, 1000);
}
}
class AutoClipTimer extends Timer {
public TimerTask schedule(final Runnable r, long delay) {
final TimerTask task = new TimerTask() {
@Override
public void run() {
r.run();
}};
this.schedule(task, delay);
return task;
}
}
class PartnerThreadLocal {
public static ThreadLocal<Long> partnerThreadLocal = new ThreadLocal<>();
public static int i ;
public static void setPartnerId(Long partnerId) {
partnerThreadLocal.set(partnerId);
}
public static Long getPartnerId() {
return partnerThreadLocal.get();
}
public static int getI() {
return i;
}
public static void setI(int i) {
PartnerThreadLocal.i = i;
}
}