java多线程学习之ThreadLocal

ThreadLocal介绍

并发程序最关键的一方面就是数据共享。当你创建了一个实现了Runable
ThreadLocal为每个使用它的线程提供单独的线程局部变量副本,每个线程都只能看到与自己关联的值,而不知道其他线程可能正在使用或者修改它们自己的副本。
ThreadLocal采用空间换时间的方式来解决线程安全问题。ThreadLocal会把共享变量复制一份到本地线程内存中,然后在自己的线程内对变量副本进行操作,各个线程只操作自己的变量副本而不影响其他线程的变量副本。

ThreadLocal 使用

代码一:

/**
 * @author Aaron
 * @Date 2019/4/16 21:42
 **/
public class ThreadLocalBean {

    private ThreadLocal threadLocal = new ThreadLocal(){
        @Override
        protected Integer initialValue() {
            return 10;
        }
    };


    public Integer get(){
        return threadLocal.get();
    }

    public void set(){
        threadLocal.set(get() + 10);
    }


    public static void main(String[] args) {
        ThreadLocal threadLocal = new ThreadLocal<>();
        System.out.println(threadLocal.get());
    }
}

代码二:

/**
 * @author Aaron
 * @Date 2019/4/15 16:40
 **/
public class ThreadLocalDemo {

    public static void main(String[] args) {
        ThreadLocalBean bean = new ThreadLocalBean();
        TempThread tempThread1 = new TempThread(bean);
        TempThread tempThread2 = new TempThread(bean);
        Thread thread1 = new Thread(tempThread1 , "thread1");
        Thread thread2 = new Thread(tempThread2 , "thread2");

        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("bean value:"+bean.get());
    }


    static class TempThread implements Runnable{
        ThreadLocalBean bean;

        public TempThread(ThreadLocalBean bean){
            this.bean = bean;
        }

        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                bean.set();
            }
            System.out.println(Thread.currentThread().getName()+"---"+bean.get());
        }
    }

}
运行结果
thread2---60
thread1---60
bean value:10

从运行结果我们发现,在thread2和thread1分别调用同一个ThreadLocalBean 的set()方法,两者的运行结果相同并且互不影响,同时这两线程对bean的操作也没有影响到bean的ThreadLocal里的值。

ThreadLocal使用场景

当你在做一个电商应用的时候,你有一个需求是为每个用户访问controller时生成一个唯一的事务ID,并且为了登录需要把这个事务ID传给业务逻辑层。一个解决方案就是把事务ID传给所有业务方法,这样的话代码就是变得冗余也没必要这样。
为了解决这个,你可以使用ThreadLocal局部变量。你可以在controller 或者预处理拦截器中生成一个事务ID,然后把它设置到ThreadLocal变量里面,之后不管什么方法调用controller里面方法,它们都能够从ThreadLocal获取到事务ID。这样controller将会处理更多的请求,并且每个请求在框架层面都是互相隔离的,事务id对每个线程都是惟一的,并且可以从线程的所有执行路径访问它

你可能感兴趣的:(并发编程)