每个Thread内有自己的实例副本,不共享。
    强调的是同一个请求内(同一个线程内)不同方法间的共享;
    不需要重写initialValue()方法,但是必须手动调用set()方法
    两大使用场景:

    典型场景1
    每个线程需要一个独享的对象(通常是工具类典型需要使用的类有SimpleDateFormat和Random);例如:SimpleDateFormat 使用2个线程格式化时间,当使用线程池时,所有的线程都共用一个simpleDateFormat对象,就会出现线程安全问题,出现打印相同的时间;
    典型场景2:每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以使用不同方法直接使用,避免参数传递的麻烦
    1.用 ThreadLocal保存一些业务内容(用户权限信息,从用户系统获取到的用户名,user ID等)
    2.这些信息在同一个线程内相同,但是不同业务的线程使用的业务内容是不同的
    3.在线程生命周期内,都通过这个静态ThreadLocal实例的get()方法取得自己set过的那个对象,避免了将这个对象(例如user对象)作为参数传递的麻烦
    1. <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;
        }
    }