定义:提供线程局部变量;一个线程局部变量在多个线程中,分别有独立的值(副本)。
特点:简单(开销即用),快速(无额外开销),安全(线程安全)
场景:多线程场景(资源持有,线程一致性,并发计算,线程安全等)
实现原理:java中用哈希表实现
基本API:
构造函数:ThreadLocal ()
初始化:initialValue()
访问器:get/set
回收:remove
public class Basic {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
//附初始值
@Override
protected Integer initialValue() {
System.out.println("initial value run..");
return 0;
}
};
public static void main(String[] args) {
threadLocal.set(10);
threadLocal.remove();
System.out.println(threadLocal.get());//若之前没有set,则会执行initialValue为其附初始值
}
}
并发计算场景:
当有10000个请求100个线程同时请求add接口时,输出结果为10000
@RestController
@RequestMapping("/stat")
public class StatController {
//用Set保存各个线程的值
static Set<Val<Integer>> set = new HashSet<>();
//因为Set可能存在于任何一个线程中,所以set.add(val)是临界区,会产生同步问题,即要加上同步锁
synchronized static void addSet(Val<Integer> val) {
set.add(val);
}
static ThreadLocal<Val<Integer>> c = new ThreadLocal<Val<Integer>>() {
@Override
protected Val<Integer> initialValue() {
Val v = new Val();
v.set(0);
addSet(v);
return v;
}
};
@RequestMapping("/get")
public Integer get() {
return set.stream().map(x -> x.get()).reduce((a, x) -> a + x).get();
}
@RequestMapping("/add")
public void set() throws InterruptedException {
Thread.sleep(500);
Val<Integer> v = c.get();
v.set(v.get() + 1);
}
}