每个Thread内有自己的实例副本,不共享。
强调的是同一个请求内(同一个线程内)不同方法间的共享;
不需要重写initialValue()方法,但是必须手动调用set()方法
两大使用场景:
典型场景1: 每个线程需要一个独享的对象(通常是工具类典型需要使用的类有SimpleDateFormat和Random);例如:SimpleDateFormat 使用2个线程格式化时间,当使用线程池时,所有的线程都共用一个simpleDateFormat对象,就会出现线程安全问题,出现打印相同的时间; 典型场景2:每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以使用不同方法直接使用,避免参数传递的麻烦 1.用 ThreadLocal保存一些业务内容(用户权限信息,从用户系统获取到的用户名,user ID等) 2.这些信息在同一个线程内相同,但是不同业务的线程使用的业务内容是不同的 3.在线程生命周期内,都通过这个静态ThreadLocal实例的get()方法取得自己set过的那个对象,避免了将这个对象(例如user对象)作为参数传递的麻烦 |
---|
<br />不同的线程中传递user对象,比如第一个线程的user对象的name是用户A,第二个线程的user对象的name是用户B, 用户A在service1中设置完成后在service2,service3中都能拿到值同样的第二个线程也是
public class ThreadLocalDemo02 {
public static void main(String[] args) {
new Service1().process();
}
}
class Service1{
public void process(){
User user = new User("三哥");
UserContextHolder.holder.set(user);
new Service2().process();
}
}
class Service2{
public void process(){
User user = UserContextHolder.holder.get();
System.out.println("service2拿到用户名:"+user.name);
new Service3().process();
}
}
class Service3{
public void process(){
User user = UserContextHolder.holder.get();
System.out.println("service3拿到用户名:"+user.name);
UserContextHolder.holder.remove();
}
}
class UserContextHolder{
public static ThreadLocal<User> holder = new ThreadLocal<>();
}
class User{
String name;
public User(String name) {
this.name = name;
}
}