对ThreadLocal的理解

from: http://blog.abreaking.com

Preface

参考:http://www.cnblogs.com/dolphin0520/p/3920407.html

在Java并发编程中,最主要问题就是对共享的资源如何进行合理的调配。因为多个线程访问同一个资源时难免会有临界区的冲突,一般的解决方式都是进行合理的加锁。加锁的一个最大问题就是对程序的效率打折扣。但有时候,线程之间访问的同一个资源,这个资源在各个线程中是相互独立的,也就是说,A线程拥有的同B线程的资源,即使A线程对该资源被修改或其他操作,不影响B线程中该资源的值。在JDK中,就有这么一个类用于专门应用这种情况:ThreadLocal。

顾名思义,该类的字面意思就是 线程本地,网上其他也叫线程本地变量存储线程本地存储。 ThreadLocal可以针对某个资源变量为每个线程创建一个属于自己的副本变量。

ThreadLocal使用

ThreadLocal有四个方法:

public T get() { }
public void set(T value) { }
public void remove() { }
protected T initialValue() { }

get()即获取该副本变量;set()即设置副本变量;remove()即删除该副本变量;

initialValue()该方法交由子类去实现,设置一个初值,当没有set()值,使用get()方法就获取到该从初值

举个例子

在Holder类中有一个变量value,就作为线程要访问的资源,指定该资源的set及get方法。如下:

   static class Holder{
        //为每个线程在内部都会创建一个属于自己的变量副本
        private static final ThreadLocal threadLocalContext = new ThreadLocal();        
        //作为资源
        String value;
        public void setValue(String value){
            threadLocalContext.set(value);
        }

        public String get(){
            return threadLocalContext.get();
        }
    }

定义线程的简单的操作,即设置下value,获取一下value。

class MyThread extends Thread{
        String value;
        public MyThread(String value){
            this.value = value;
        }
        @Override
        public void run() {
            holder.setValue(value);
            System.out.println("测试线程的值:"+holder.get());
        }
    }

主线程也是同样的操作,采用主线程与测试线程并发的操作,如下:

    @Test
    public void test01() throws InterruptedException {
        MyThread testThread = new MyThread("test");

        holder.setValue("main");
        System.out.println("main线程的值:"+holder.get());

        testThread.start();
        Thread.sleep(1000);

        System.out.println("main线程的值:"+holder.get());
    }

结果如下:

对ThreadLocal的理解_第1张图片

可见,一个线程对资源的改变并没有对另一个线程拥有的资源副本有影响。

反例

针对Holder类,如果不使用ThreadLocal,那么线程之间使用就是同一个资源了,该资源的修改肯定会影响其他线程了。如,我们直接使用最简单的set及get

    static class Holder{
        //作为资源
        String value;
        public void setValue(String value){
            this.value = value;
        }

        public String get(){
            return  this.value;
        }
    }

 其他部分不变,这时再查看结果:

应用场景

ThreadLocal使用最广泛的就是Session之间的数据源连接Connection,以及多数据源的管理。

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